twitterchiver/viewer: swap openshiftauth for pomerium
This commit is contained in:
parent
e3b60baa72
commit
3a3acc4673
10 changed files with 95 additions and 361 deletions
|
@ -5,6 +5,5 @@
|
||||||
args: {
|
args: {
|
||||||
twitterchiver = import ./twitterchiver args;
|
twitterchiver = import ./twitterchiver args;
|
||||||
twitternuke = import ./twitternuke args;
|
twitternuke = import ./twitternuke args;
|
||||||
openshiftauth = import ./openshiftauth args;
|
|
||||||
minotarproxy = import ./minotarproxy args;
|
minotarproxy = import ./minotarproxy args;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,5 +16,6 @@ require (
|
||||||
github.com/gorilla/sessions v1.2.1
|
github.com/gorilla/sessions v1.2.1
|
||||||
github.com/jackc/pgtype v1.4.2
|
github.com/jackc/pgtype v1.4.2
|
||||||
github.com/jackc/pgx/v4 v4.8.1
|
github.com/jackc/pgx/v4 v4.8.1
|
||||||
|
github.com/pomerium/sdk-go v0.0.5 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
|
||||||
)
|
)
|
||||||
|
|
11
go/go.sum
11
go/go.sum
|
@ -32,6 +32,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
@ -127,6 +128,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/pomerium/sdk-go v0.0.5 h1:8iJg/uZ7AmhGfHvmHmpZOswzg9MDMcmpTMX0zpmDxxs=
|
||||||
|
github.com/pomerium/sdk-go v0.0.5/go.mod h1:z4HXhKxVTIQqmffpjQP6Oi+oP9r37a0Kx/jq69jcNRo=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||||
|
@ -145,6 +148,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
|
@ -163,6 +167,8 @@ golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
|
||||||
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||||
|
@ -201,8 +207,10 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
|
@ -242,8 +250,11 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s=
|
||||||
|
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||||
|
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
{ depot, ... }: {
|
|
||||||
openshiftauth = depot.third_party.buildGo.package {
|
|
||||||
name = "hg.lukegb.com/lukegb/depot/go/openshiftauth";
|
|
||||||
srcs = [ ./openshiftauth.go ];
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
gopkgs."github.com".dghubble.gologin.v2
|
|
||||||
gopkgs."github.com".dghubble.gologin.v2.oauth2
|
|
||||||
gopkgs."github.com".dgrijalva.jwt-go
|
|
||||||
gopkgs."github.com".gorilla.mux
|
|
||||||
gopkgs."github.com".gorilla.securecookie
|
|
||||||
gopkgs."github.com".gorilla.sessions
|
|
||||||
gopkgs."golang.org".x.oauth2
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
example = depot.third_party.buildGo.program {
|
|
||||||
name = "example";
|
|
||||||
srcs = [ ./example/example.go ];
|
|
||||||
deps = with depot.third_party; [
|
|
||||||
depot.go.openshiftauth.openshiftauth
|
|
||||||
gopkgs."github.com".gorilla.mux
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"hg.lukegb.com/lukegb/depot/go/openshiftauth"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
r := mux.NewRouter()
|
|
||||||
authR, err := openshiftauth.NewRouter(r)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("openshiftauth.NewRouter: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
authR.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
u := openshiftauth.UserFromContext(r.Context())
|
|
||||||
rw.Header().Set("Content-Type", "application/json")
|
|
||||||
enc := json.NewEncoder(rw)
|
|
||||||
enc.SetIndent("", " ")
|
|
||||||
enc.Encode(u)
|
|
||||||
})
|
|
||||||
r.HandleFunc("/healthz", func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
rw.Header().Set("Content-Type", "text/plain")
|
|
||||||
fmt.Fprintf(rw, "ok")
|
|
||||||
})
|
|
||||||
|
|
||||||
http.Handle("/", r)
|
|
||||||
http.ListenAndServe(":8080", nil)
|
|
||||||
}
|
|
|
@ -1,285 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: Apache-2.0
|
|
||||||
package openshiftauth
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/gob"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/dghubble/gologin/v2"
|
|
||||||
"github.com/dghubble/gologin/v2/oauth2"
|
|
||||||
"github.com/dgrijalva/jwt-go"
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/gorilla/securecookie"
|
|
||||||
"github.com/gorilla/sessions"
|
|
||||||
xoauth2 "golang.org/x/oauth2"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SecretGetter func(ctx context.Context) (string, error)
|
|
||||||
|
|
||||||
func TokenDirSecretGetter(ctx context.Context) (string, error) {
|
|
||||||
v, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("couldn't read serviceaccount secret: %w", err)
|
|
||||||
}
|
|
||||||
return string(v), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type BaseHandler struct {
|
|
||||||
Config xoauth2.Config
|
|
||||||
SecretGetter SecretGetter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *BaseHandler) config(ctx context.Context) (*xoauth2.Config, error) {
|
|
||||||
s, err := h.SecretGetter(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cfg := h.Config
|
|
||||||
cfg.ClientSecret = s
|
|
||||||
return &cfg, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *BaseHandler) wrapWithConfig(f func(cfg *xoauth2.Config) http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
cfg, err := h.config(r.Context())
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
f(cfg).ServeHTTP(rw, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *BaseHandler) CallbackHandler(success, failure http.Handler) http.Handler {
|
|
||||||
return h.wrapWithConfig(func(cfg *xoauth2.Config) http.Handler {
|
|
||||||
return oauth2.CallbackHandler(cfg, success, failure)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *BaseHandler) LoginHandler(failure http.Handler) http.Handler {
|
|
||||||
return h.wrapWithConfig(func(cfg *xoauth2.Config) http.Handler {
|
|
||||||
return oauth2.LoginHandler(cfg, failure)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type contextKey string
|
|
||||||
|
|
||||||
const (
|
|
||||||
sessionContextKey contextKey = "session"
|
|
||||||
)
|
|
||||||
|
|
||||||
func AttachSessionMiddleware(sess sessions.Store) func(http.Handler) http.Handler {
|
|
||||||
return func(next http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
s, err := sess.Get(r, "openshiftauth")
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("decoding session: %v", err)
|
|
||||||
}
|
|
||||||
ctx := context.WithValue(r.Context(), sessionContextKey, s)
|
|
||||||
next.ServeHTTP(w, r.WithContext(ctx))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Session(ctx context.Context) *sessions.Session {
|
|
||||||
return ctx.Value(sessionContextKey).(*sessions.Session)
|
|
||||||
}
|
|
||||||
|
|
||||||
func UserFromContext(ctx context.Context) *User {
|
|
||||||
s := Session(ctx)
|
|
||||||
if s.Values["user"] != nil {
|
|
||||||
return s.Values["user"].(*User)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func secretFromEnv(name string, length int) []byte {
|
|
||||||
var bs []byte
|
|
||||||
if bsHex, ok := os.LookupEnv(name); ok {
|
|
||||||
newBS, err := hex.DecodeString(bsHex)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("failed to decode %v as hex: %v", name, err)
|
|
||||||
} else {
|
|
||||||
bs = newBS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if bs == nil {
|
|
||||||
log.Printf("generating a random %v: this is bad", name)
|
|
||||||
bs = securecookie.GenerateRandomKey(length)
|
|
||||||
}
|
|
||||||
return bs
|
|
||||||
}
|
|
||||||
|
|
||||||
type User struct {
|
|
||||||
Metadata struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
} `json:"metadata"`
|
|
||||||
FullName string `json:"fullName"`
|
|
||||||
Identities []string `json:"identities"`
|
|
||||||
Groups []string `json:"groups"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
gob.Register(&User{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func fetchUserForToken(ctx context.Context, token *xoauth2.Token) (*User, error) {
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", "https://api.k8s.lukegb.tech:6443/apis/user.openshift.io/v1/users/~", nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("http.NewRequestWithContext for users/~ failed")
|
|
||||||
}
|
|
||||||
token.SetAuthHeader(req)
|
|
||||||
resp, err := http.DefaultClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("executing request for users/~ failed: %v", err)
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
|
||||||
return nil, fmt.Errorf("openshift returned non-OK status %d %v", resp.StatusCode, resp.Status)
|
|
||||||
}
|
|
||||||
|
|
||||||
var u User
|
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&u); err != nil {
|
|
||||||
return nil, fmt.Errorf("decoding response from openshift: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &u, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func RequireAuth(next http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
u := UserFromContext(r.Context())
|
|
||||||
if u == nil {
|
|
||||||
redirURL := r.URL.ResolveReference(r.URL)
|
|
||||||
redirURL.Path = "/.login/start"
|
|
||||||
redirURL.RawQuery = url.Values{
|
|
||||||
"next": []string{r.URL.String()},
|
|
||||||
}.Encode()
|
|
||||||
http.Redirect(rw, r, redirURL.String(), http.StatusSeeOther)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
next.ServeHTTP(rw, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
type serviceAccountDetails struct {
|
|
||||||
Namespace string `json:"kubernetes.io/serviceaccount/namespace"`
|
|
||||||
Name string `json:"kubernetes.io/serviceaccount/service-account.name"`
|
|
||||||
FullName string `json:"sub"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseServiceAccount() (*serviceAccountDetails, error) {
|
|
||||||
token, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/token")
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("reading service account JWT: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseUnverified is safe here because we're just using it to extract information about ourselves.
|
|
||||||
p := &jwt.Parser{}
|
|
||||||
claims := make(jwt.MapClaims)
|
|
||||||
if _, _, err := p.ParseUnverified(string(token), claims); err != nil {
|
|
||||||
return nil, fmt.Errorf("parsing JWT: %w", err)
|
|
||||||
}
|
|
||||||
val := func(s string) string {
|
|
||||||
v, ok := claims[s]
|
|
||||||
if !ok {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return v.(string)
|
|
||||||
}
|
|
||||||
sad := &serviceAccountDetails{
|
|
||||||
Namespace: val("kubernetes.io/serviceaccount/namespace"),
|
|
||||||
Name: val("kubernetes.io/serviceaccount/service-account.name"),
|
|
||||||
FullName: val("sub"),
|
|
||||||
}
|
|
||||||
return sad, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRouter(r *mux.Router) (*mux.Router, error) {
|
|
||||||
sess := sessions.NewCookieStore(
|
|
||||||
secretFromEnv("OPENSHIFT_AUTH_SESSION_SIGN_SECRET", 32),
|
|
||||||
secretFromEnv("OPENSHIFT_AUTH_SESSION_ENC_SECRET", 32))
|
|
||||||
r.Use(AttachSessionMiddleware(sess))
|
|
||||||
|
|
||||||
sad, err := parseServiceAccount()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("loading service account information: %w", err)
|
|
||||||
}
|
|
||||||
log.Printf("using service account token for %v", sad.FullName)
|
|
||||||
|
|
||||||
bh := &BaseHandler{
|
|
||||||
Config: xoauth2.Config{
|
|
||||||
ClientID: sad.FullName,
|
|
||||||
Endpoint: xoauth2.Endpoint{
|
|
||||||
AuthURL: "https://oauth-openshift.apps.k8s.lukegb.tech/oauth/authorize",
|
|
||||||
TokenURL: "https://oauth-openshift.apps.k8s.lukegb.tech/oauth/token",
|
|
||||||
},
|
|
||||||
RedirectURL: fmt.Sprintf("%s/.login/callback", os.Getenv("OPENSHIFT_AUTH_BASE")),
|
|
||||||
Scopes: []string{"user:info"},
|
|
||||||
},
|
|
||||||
SecretGetter: TokenDirSecretGetter,
|
|
||||||
}
|
|
||||||
baseURL, err := url.Parse(os.Getenv("OPENSHIFT_AUTH_BASE"))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to parse OPENSHIFT_AUTH_BASE as URL: %v", err)
|
|
||||||
}
|
|
||||||
stateConfig := gologin.DefaultCookieConfig
|
|
||||||
r.HandleFunc("/.login/start", func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
ctx := r.Context()
|
|
||||||
if nextURL, err := url.Parse(r.URL.Query().Get("next")); err == nil {
|
|
||||||
nextURL = baseURL.ResolveReference(nextURL)
|
|
||||||
if nextURL.Scheme != baseURL.Scheme || nextURL.User != nil || nextURL.Host != baseURL.Host {
|
|
||||||
nextURL = nil
|
|
||||||
}
|
|
||||||
if nextURL != nil {
|
|
||||||
s := Session(ctx)
|
|
||||||
s.AddFlash(nextURL.RequestURI(), "_openshiftauth_next")
|
|
||||||
sessions.Save(r, rw)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
oauth2.StateHandler(stateConfig, bh.LoginHandler(nil)).ServeHTTP(rw, r)
|
|
||||||
})
|
|
||||||
r.Handle("/.login/callback", oauth2.StateHandler(stateConfig, bh.CallbackHandler(
|
|
||||||
http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
ctx := r.Context()
|
|
||||||
token, err := oauth2.TokenFromContext(ctx)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, "oauth2 TokenFromContext failed", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
u, err := fetchUserForToken(ctx, token)
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, fmt.Sprintf("fetchUserForToken: %v", err), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
s := Session(ctx)
|
|
||||||
s.Values["user"] = *u
|
|
||||||
sessions.Save(r, rw)
|
|
||||||
|
|
||||||
next := "/"
|
|
||||||
nexts := s.Flashes("_openshiftauth_next")
|
|
||||||
if len(nexts) >= 1 {
|
|
||||||
next = nexts[0].(string)
|
|
||||||
}
|
|
||||||
http.Redirect(rw, r, next, http.StatusFound)
|
|
||||||
}),
|
|
||||||
nil)))
|
|
||||||
|
|
||||||
authR := r.PathPrefix("/").Subrouter()
|
|
||||||
authR.Use(RequireAuth)
|
|
||||||
|
|
||||||
return authR, nil
|
|
||||||
}
|
|
|
@ -22,7 +22,7 @@
|
||||||
depot.third_party.gopkgs."github.com".gorilla.mux
|
depot.third_party.gopkgs."github.com".gorilla.mux
|
||||||
depot.third_party.gopkgs."github.com".jackc.pgtype
|
depot.third_party.gopkgs."github.com".jackc.pgtype
|
||||||
depot.third_party.gopkgs."github.com".jackc.pgx.v4.pgxpool
|
depot.third_party.gopkgs."github.com".jackc.pgx.v4.pgxpool
|
||||||
depot.go.openshiftauth.openshiftauth
|
depot.third_party.gopkgs."github.com".pomerium.sdk-go
|
||||||
];
|
];
|
||||||
dockerData = [ (
|
dockerData = [ (
|
||||||
depot.pkgs.runCommand "source" {} ''
|
depot.pkgs.runCommand "source" {} ''
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/jackc/pgtype"
|
"github.com/jackc/pgtype"
|
||||||
"github.com/jackc/pgx/v4/pgxpool"
|
"github.com/jackc/pgx/v4/pgxpool"
|
||||||
"hg.lukegb.com/lukegb/depot/go/openshiftauth"
|
pomerium "github.com/pomerium/sdk-go"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -100,6 +100,17 @@ func bestVariant(vs []interface{}) interface{} {
|
||||||
return bestVariant
|
return bestVariant
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mapDatastore map[interface{}]interface{}
|
||||||
|
|
||||||
|
func (ds mapDatastore) Get(key interface{}) (value interface{}, ok bool) {
|
||||||
|
value, ok = ds[key]
|
||||||
|
return value, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds mapDatastore) Add(key, value interface{}) {
|
||||||
|
ds[key] = value
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
@ -117,20 +128,30 @@ func main() {
|
||||||
})
|
})
|
||||||
|
|
||||||
var authR *mux.Router
|
var authR *mux.Router
|
||||||
if *localDisableAuth != "" {
|
var v *pomerium.Verifier
|
||||||
authR = r
|
if *localDisableAuth == "" {
|
||||||
} else {
|
authR = r.PathPrefix("/").Subrouter()
|
||||||
authR, err = openshiftauth.NewRouter(r)
|
var err error
|
||||||
|
v, err = pomerium.New(&pomerium.Options{
|
||||||
|
JWKSEndpoint: "https://auth.int.lukegb.com/.well-known/pomerium/jwks.json",
|
||||||
|
Datastore: mapDatastore{},
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("openshiftauth.NewRouter: %v", err)
|
log.Fatalf("pomerium.New: %v", err)
|
||||||
}
|
}
|
||||||
|
authR.Use(pomerium.AddIdentityToRequest(v))
|
||||||
}
|
}
|
||||||
|
authR = r
|
||||||
|
|
||||||
userFromContext := func(ctx context.Context) string {
|
userFromContext := func(ctx context.Context) (string, error) {
|
||||||
if *localDisableAuth != "" {
|
if *localDisableAuth != "" {
|
||||||
return *localDisableAuth
|
return *localDisableAuth, nil
|
||||||
}
|
}
|
||||||
return openshiftauth.UserFromContext(ctx).Metadata.Name
|
identity, err := pomerium.FromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return identity.User, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
writeError := func(rw http.ResponseWriter, status int, wrap string, err error) {
|
writeError := func(rw http.ResponseWriter, status int, wrap string, err error) {
|
||||||
|
@ -143,7 +164,11 @@ func main() {
|
||||||
authR.PathPrefix("/media/").Handler(http.StripPrefix("/media/", http.FileServer(http.Dir(*mediaDirectory))))
|
authR.PathPrefix("/media/").Handler(http.StripPrefix("/media/", http.FileServer(http.Dir(*mediaDirectory))))
|
||||||
authR.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
|
authR.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
user := userFromContext(ctx)
|
user, err := userFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, fmt.Errorf("userFromContext: %w", err).Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
twitterAccounts := userMapping[user]
|
twitterAccounts := userMapping[user]
|
||||||
|
|
||||||
var allTweets, timelineTweets, unfetchedMedia, unfetchedRelated int
|
var allTweets, timelineTweets, unfetchedMedia, unfetchedRelated int
|
||||||
|
@ -214,7 +239,11 @@ ORDER BY 1
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
isAllowedToSee := func(ctx context.Context, twitterUser string) bool {
|
isAllowedToSee := func(ctx context.Context, twitterUser string) bool {
|
||||||
twitterAccounts := userMapping[userFromContext(ctx)]
|
user, err := userFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
twitterAccounts := userMapping[user]
|
||||||
for _, a := range twitterAccounts {
|
for _, a := range twitterAccounts {
|
||||||
if a == twitterUser {
|
if a == twitterUser {
|
||||||
return true
|
return true
|
||||||
|
@ -241,8 +270,13 @@ ORDER BY 1
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
vars := mux.Vars(r)
|
vars := mux.Vars(r)
|
||||||
twitterUser := vars["twitterUser"]
|
twitterUser := vars["twitterUser"]
|
||||||
|
user, err := userFromContext(ctx)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(rw, fmt.Errorf("userFromContext: %w", err).Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
if !isAllowedToSee(ctx, twitterUser) {
|
if !isAllowedToSee(ctx, twitterUser) {
|
||||||
writeError(rw, http.StatusNotFound, "no such twitter user being archived", fmt.Errorf("user %q attempted to access %q", userFromContext(ctx), twitterUser))
|
writeError(rw, http.StatusNotFound, "no such twitter user being archived", fmt.Errorf("user %q attempted to access %q", user, twitterUser))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
third_party/gopkgs/github.com/pomerium/sdk-go/default.nix
vendored
Normal file
18
third_party/gopkgs/github.com/pomerium/sdk-go/default.nix
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
{ depot, ... }:
|
||||||
|
depot.third_party.buildGo.external {
|
||||||
|
path = "github.com/pomerium/sdk-go";
|
||||||
|
src = depot.third_party.nixpkgs.fetchFromGitHub {
|
||||||
|
owner = "pomerium";
|
||||||
|
repo = "sdk-go";
|
||||||
|
rev = "v0.0.5";
|
||||||
|
hash = "sha256:08sa6jzixw09w519lr69wb69z7hx1158jbji9kh6f9wvxp0ny9lw";
|
||||||
|
};
|
||||||
|
deps = with depot.third_party; [
|
||||||
|
gopkgs."gopkg.in".square."go-jose.v2"
|
||||||
|
gopkgs."gopkg.in".square."go-jose.v2".jwt
|
||||||
|
];
|
||||||
|
}
|
18
third_party/gopkgs/gopkg.in/square/go-jose.v2/default.nix
vendored
Normal file
18
third_party/gopkgs/gopkg.in/square/go-jose.v2/default.nix
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# SPDX-FileCopyrightText: 2020 Luke Granger-Brown <depot@lukegb.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
{ depot, ... }:
|
||||||
|
depot.third_party.buildGo.external {
|
||||||
|
path = "gopkg.in/square/go-jose.v2";
|
||||||
|
src = depot.third_party.nixpkgs.fetchFromGitHub {
|
||||||
|
owner = "square";
|
||||||
|
repo = "go-jose";
|
||||||
|
rev = "v2.5.1";
|
||||||
|
hash = "sha256:0z0hbmb5yyvnjkyiyn259wkbqbjxs2pzx87jz472shn2bgggxa4n";
|
||||||
|
};
|
||||||
|
deps = with depot.third_party; [
|
||||||
|
gopkgs."golang.org".x.crypto.ed25519
|
||||||
|
gopkgs."golang.org".x.crypto.pbkdf2
|
||||||
|
];
|
||||||
|
}
|
Loading…
Reference in a new issue