diff --git a/.drone.yml b/.drone.yml index be4bc2f..ce196cc 100644 --- a/.drone.yml +++ b/.drone.yml @@ -5,34 +5,33 @@ type: docker name: test-build steps: -- name: go-test - image: golang - commands: - - make -C template test - depends_on: + - name: go-test + image: golang + commands: + - make -C polyculeconnect test + depends_on: -- name: go-build - image: golang - commands: - - make -C template build - depends_on: - -- name: docker-build-only - image: thegeeklab/drone-docker-buildx - privileged: true - settings: - repo: git.faercol.me/go-web-template - tags: latest - dry_run: true - platforms: - - linux/amd64 - - linux/arm64 - depends_on: - when: - branch: - exclude: - - main + - name: go-build + image: golang + commands: + - make -C polyculeconnect build + depends_on: + - name: docker-build-only + image: thegeeklab/drone-docker-buildx + privileged: true + settings: + repo: git.faercol.me/polyculeconnect/polyculeconnect + tags: latest + dry_run: true + platforms: + - linux/amd64 + - linux/arm64 + depends_on: + when: + branch: + exclude: + - main # - name: docker-build-push # image: thegeeklab/drone-docker-buildx # privileged: true @@ -87,4 +86,3 @@ steps: # event: # - tag -... \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..24f10c1 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM --platform=$TARGETPLATFORM golang:1.20 AS builder +ARG TARGETPLATFORM +ARG BUILDPLATFORM +WORKDIR /go/src/git.faercol.me/polyculeconnect +COPY polyculeconnect ./ +RUN CGO_ENABLED=0 make build + +# Replace with from scratch later on +FROM --platform=$TARGETPLATFORM alpine:latest +WORKDIR /root +COPY --from=builder go/src/git.faercol.me/polyculeconnect/build/polyculeconnect ./ + +VOLUME [ "/config" ] + +ENTRYPOINT [ "./polyculeconnect" ] +CMD [ "-config", "/config/config.json" ] diff --git a/README.md b/README.md index 06c6df2..a877602 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# go-web-template +# PolyculeConnect -[![Build Status](https://drone.faercol.me/api/badges/faercol/go-web-template/status.svg)](https://drone.faercol.me/faercol/go-web-template) +[![Build Status](https://drone.faercol.me/api/badges/PolyculeConnect/polycule-connect/status.svg)](https://drone.faercol.me/PolyculeConnect/polycule-connect) -Simple template for Go modules with a Web server \ No newline at end of file +PolyculeConnect \ No newline at end of file diff --git a/polyculeconnect/config/config.go b/polyculeconnect/config/config.go index 01ab09e..d39b699 100644 --- a/polyculeconnect/config/config.go +++ b/polyculeconnect/config/config.go @@ -7,6 +7,8 @@ import ( "io/fs" "os" + "github.com/dexidp/dex/connector/oidc" + "github.com/dexidp/dex/storage" "github.com/sirupsen/logrus" ) @@ -38,6 +40,19 @@ const ( ModeNet ) +type BackendConfig struct { + Config *oidc.Config `json:"config"` + Name string `json:"name"` + ID string `json:"ID"` + Type string `json:"type"` + Local bool `json:"local"` +} + +type OpenConnectConfig struct { + ClientConfigs []*storage.Client `json:"clients"` + BackendConfigs []*BackendConfig `json:"backends"` +} + type jsonConf struct { Log struct { Level string `json:"level"` @@ -48,14 +63,16 @@ type jsonConf struct { Mode string `json:"mode"` SockPath string `json:"sock"` } `json:"server"` + OpenConnectConfig *OpenConnectConfig `json:"openconnect"` } type AppConfig struct { - LogLevel logrus.Level - ServerMode ListeningMode - Host string - Port int - SockPath string + LogLevel logrus.Level + ServerMode ListeningMode + Host string + Port int + SockPath string + OpenConnectConfig *OpenConnectConfig } func parseLevel(lvlStr string) logrus.Level { @@ -78,10 +95,13 @@ func (ac *AppConfig) UnmarshalJSON(data []byte) error { if err != nil { return fmt.Errorf("failed to parse server listening mode: %w", err) } + + fmt.Println(jsonConf) ac.ServerMode = lm ac.SockPath = jsonConf.Server.SockPath ac.Host = jsonConf.Server.Host ac.Port = jsonConf.Server.Port + ac.OpenConnectConfig = jsonConf.OpenConnectConfig return nil } diff --git a/polyculeconnect/controller/ui/static.go b/polyculeconnect/controller/ui/static.go new file mode 100644 index 0000000..e16d2ff --- /dev/null +++ b/polyculeconnect/controller/ui/static.go @@ -0,0 +1,67 @@ +package ui + +import ( + "bytes" + "fmt" + "html/template" + "io" + "net/http" + "path/filepath" + + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/helpers" + "github.com/sirupsen/logrus" +) + +const StaticRoute = "/static/" + +type StaticController struct { +} + +func (sc *StaticController) ServeHTTP(w http.ResponseWriter, r *http.Request) { + fs := http.FileServer(http.Dir("./static")) + http.StripPrefix(StaticRoute, fs).ServeHTTP(w, r) +} + +type IndexController struct { + l *logrus.Logger +} + +func NewIndexController(l *logrus.Logger) *IndexController { + return &IndexController{ + l: l, + } +} + +func (ic IndexController) serveUI(w http.ResponseWriter, r *http.Request) (int, int, error) { + lp := filepath.Join("templates", "index.html") + tmpl, err := template.ParseFiles(lp) + if err != nil { + return http.StatusInternalServerError, -1, fmt.Errorf("failed to init template: %w", err) + } + buf := new(bytes.Buffer) + + if err := tmpl.Execute(buf, nil); err != nil { + return http.StatusInternalServerError, -1, fmt.Errorf("failed to execute template: %w", err) + } + n, err := io.Copy(w, buf) + if err != nil { + return http.StatusInternalServerError, int(n), fmt.Errorf("failed to write response; %w", err) + } + + return http.StatusOK, int(n), nil +} + +func (ic *IndexController) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if r.RequestURI != "/" { + ic.l.Errorf("Unhandled route %q", r.RequestURI) + helpers.HandleResponse(w, r, http.StatusNotFound, nil, ic.l) + return + } + returncode, contentLength, err := ic.serveUI(w, r) + if err != nil { + ic.l.Errorf("Error serving UI: %s", err.Error()) + helpers.HandleResponse(w, r, returncode, nil, ic.l) + } else { + helpers.AddToContext(r, returncode, contentLength) + } +} diff --git a/polyculeconnect/go.mod b/polyculeconnect/go.mod index d0ba208..8c7a0f7 100644 --- a/polyculeconnect/go.mod +++ b/polyculeconnect/go.mod @@ -1,15 +1,67 @@ -module git.faercol.me/faercol/polyculeconnect/template +module git.faercol.me/faercol/polyculeconnect/polyculeconnect go 1.20 require ( + github.com/dexidp/dex v0.0.0-20231014000322-089f374d4f3e + github.com/prometheus/client_golang v1.17.0 github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.7.0 + github.com/stretchr/testify v1.8.4 ) require ( + cloud.google.com/go/compute v1.23.0 // indirect + cloud.google.com/go/compute/metadata v0.2.3 // indirect + github.com/AppsFlyer/go-sundheit v0.5.0 // indirect + github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect + github.com/beevik/etree v1.2.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/coreos/go-oidc/v3 v3.6.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dexidp/dex/api/v2 v2.1.1-0.20231014000322-089f374d4f3e // indirect + github.com/felixge/httpsnoop v1.0.3 // indirect + github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect + github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/go-ldap/ldap/v3 v3.4.6 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/gorilla/handlers v1.5.1 // indirect + github.com/gorilla/mux v1.8.0 // indirect + github.com/huandu/xstrings v1.3.3 // indirect + github.com/imdario/mergo v0.3.11 // indirect + github.com/jonboulle/clockwork v0.2.2 // indirect + github.com/mattermost/xml-roundtrip-validator v0.1.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/copystructure v1.0.0 // indirect + github.com/mitchellh/reflectwalk v1.0.0 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect + github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.11.1 // indirect + github.com/russellhaering/goxmldsig v1.4.0 // indirect + github.com/shopspring/decimal v1.2.0 // indirect + github.com/spf13/cast v1.4.1 // indirect + go.opencensus.io v0.24.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/api v0.147.0 // indirect + google.golang.org/appengine v1.6.7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect + google.golang.org/grpc v1.58.3 // indirect + google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/polyculeconnect/go.sum b/polyculeconnect/go.sum index 9243c28..4b8f5f0 100644 --- a/polyculeconnect/go.sum +++ b/polyculeconnect/go.sum @@ -1,16 +1,291 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +github.com/AppsFlyer/go-sundheit v0.5.0 h1:/VxpyigCfJrq1r97mn9HPiAB2qrhcTFHwNIIDr15CZM= +github.com/AppsFlyer/go-sundheit v0.5.0/go.mod h1:2ZM0BnfqT/mljBQO224VbL5XH06TgWuQ6Cn+cTtCpTY= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8= +github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= +github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA= +github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4= +github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= +github.com/beevik/etree v1.2.0 h1:l7WETslUG/T+xOPs47dtd6jov2Ii/8/OjCldk5fYfQw= +github.com/beevik/etree v1.2.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/coreos/go-oidc/v3 v3.6.0 h1:AKVxfYw1Gmkn/w96z0DbT/B/xFnzTd3MkZvWLjF4n/o= +github.com/coreos/go-oidc/v3 v3.6.0/go.mod h1:ZpHUsHBucTUj6WOkrP4E20UPynbLZzhTQ1XKCXkxyPc= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dexidp/dex v0.0.0-20231014000322-089f374d4f3e h1:d/wCtR05IxnKZN9cg8YsLXPzYeDZoQsJpGoBBw2oQn4= +github.com/dexidp/dex v0.0.0-20231014000322-089f374d4f3e/go.mod h1:xFYDBaDJhmCE6xrovgHeUaFyslqhfocm3/xIJRkUYdk= +github.com/dexidp/dex/api/v2 v2.1.1-0.20231014000322-089f374d4f3e h1:46E2eP+vALmVQQz68L21EusFbwjJDCZVZT5hI1al4lE= +github.com/dexidp/dex/api/v2 v2.1.1-0.20231014000322-089f374d4f3e/go.mod h1:MwZ7k1lmdibhSptV8z+eKgZDOyAamm3M332EyQHycxA= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= +github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA= +github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= +github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= +github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A= +github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +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.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU= +github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16 h1:v7DLqVdK4VrYkVD5diGdl4sxJurKJEMnODWRJlxV9oM= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/russellhaering/goxmldsig v1.4.0 h1:8UcDh/xGyQiyrW+Fq5t8f+l2DLB1+zlhYzkPUJ7Qhys= +github.com/russellhaering/goxmldsig v1.4.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= +go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741 h1:fGZugkZk2UgYBxtpKmvub51Yno1LJDeEsRp2xGD+0gY= +golang.org/x/exp v0.0.0-20221004215720-b9f4876ce741/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= +golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/text v0.3.0/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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.147.0 h1:Can3FaQo9LlVqxJCodNmeZW/ib3/qKAY3rFeXiHo5gc= +google.golang.org/api v0.147.0/go.mod h1:pQ/9j83DcmPd/5C9e2nFOdjjNkDZ1G+zkbK2uvdkJMs= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 h1:SeZZZx0cP0fqUyA+oRzP9k7cSwJlvDFiROO72uwD6i0= +google.golang.org/genproto/googleapis/api v0.0.0-20231002182017-d307bd883b97 h1:W18sezcAYs+3tDZX4F80yctqa12jcP1PUS2gQu1zTPU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= +gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/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-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/polyculeconnect/helpers/helpers.go b/polyculeconnect/helpers/helpers.go new file mode 100644 index 0000000..035ed63 --- /dev/null +++ b/polyculeconnect/helpers/helpers.go @@ -0,0 +1,36 @@ +package helpers + +import ( + "context" + "net/http" + + "github.com/sirupsen/logrus" +) + +type ContextKey string + +const ResponseInfoKey ContextKey = "response_info" + +type ResponseInfo struct { + ReturnCode int + ContentLength int +} + +func HandleResponse(w http.ResponseWriter, r *http.Request, returncode int, content []byte, l *logrus.Logger) { + w.WriteHeader(returncode) + n, err := w.Write(content) + if err != nil { + l.Errorf("Failed to write content to response: %q", err.Error()) + } + if n != len(content) { + l.Errorf("Failed to write the entire response (%d/%d)", n, len(content)) + } + + contextedReq := r.WithContext(context.WithValue(r.Context(), ResponseInfoKey, ResponseInfo{ReturnCode: returncode, ContentLength: len(content)})) + *r = *contextedReq +} + +func AddToContext(r *http.Request, returncode, contentLength int) { + contextedReq := r.WithContext(context.WithValue(r.Context(), ResponseInfoKey, ResponseInfo{ReturnCode: returncode, ContentLength: contentLength})) + *r = *contextedReq +} diff --git a/polyculeconnect/main.go b/polyculeconnect/main.go index bcbe095..c670e2b 100644 --- a/polyculeconnect/main.go +++ b/polyculeconnect/main.go @@ -2,14 +2,19 @@ package main import ( "context" + "encoding/json" "flag" "os" "os/signal" "time" - "git.faercol.me/faercol/polyculeconnect/template/config" - "git.faercol.me/faercol/polyculeconnect/template/logger" - "git.faercol.me/faercol/polyculeconnect/template/server" + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/config" + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/logger" + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/server" + dex_server "github.com/dexidp/dex/server" + "github.com/dexidp/dex/storage" + "github.com/dexidp/dex/storage/memory" + "github.com/prometheus/client_golang/prometheus" ) const stopTimeout = 10 * time.Second @@ -41,8 +46,52 @@ func main() { logger.Init(conf.LogLevel) logger.L.Infof("Initialized logger with level %v", conf.LogLevel) + dexConf := dex_server.Config{ + Web: dex_server.WebConfig{ + Dir: "./", + Theme: "default", + }, + Storage: memory.New(logger.L), + Issuer: "http://127.0.0.1:5000", + SupportedResponseTypes: []string{"code"}, + SkipApprovalScreen: true, + AllowedOrigins: []string{"*"}, + Logger: logger.L, + PrometheusRegistry: prometheus.NewRegistry(), + } + + logger.L.Info("Initializing authentication backends") + for _, backend := range conf.OpenConnectConfig.BackendConfigs { + backendConfJson, err := json.Marshal(backend.Config) + if err != nil { + logger.L.Errorf("Failed to serialize oidc config for backend %q: %s", backend.Name, err) + continue + } + if err := dexConf.Storage.CreateConnector(storage.Connector{ + ID: backend.ID, + Name: backend.Name, + Type: backend.Type, + Config: backendConfJson, + }); err != nil { + logger.L.Errorf("Failed to add connector for backend %q to stage: %s", backend.Name, err) + continue + } + } + + logger.L.Info("Initializing clients") + for _, client := range conf.OpenConnectConfig.ClientConfigs { + if err := dexConf.Storage.CreateClient(*client); err != nil { + logger.L.Errorf("Failed to add client to storage: %s", err.Error()) + } + } + + dexSrv, err := dex_server.NewServer(mainCtx, dexConf) + if err != nil { + logger.L.Fatalf("Failed to init dex server: %s", err.Error()) + } + logger.L.Info("Initializing server") - s, err := server.New(conf, logger.L) + s, err := server.New(conf, dexSrv, logger.L) if err != nil { logger.L.Fatalf("Failed to initialize server: %s", err.Error()) } diff --git a/polyculeconnect/middlewares/logger.go b/polyculeconnect/middlewares/logger.go new file mode 100644 index 0000000..79217b6 --- /dev/null +++ b/polyculeconnect/middlewares/logger.go @@ -0,0 +1,39 @@ +package middlewares + +import ( + "net" + "net/http" + "time" + + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/helpers" + "github.com/sirupsen/logrus" +) + +var defaultResponseInfo = helpers.ResponseInfo{ + ReturnCode: -1, + ContentLength: -1, +} + +type LoggerMiddleware struct { + l *logrus.Logger +} + +func (lm *LoggerMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) { + responseInfo, ok := r.Context().Value(helpers.ResponseInfoKey).(helpers.ResponseInfo) + if !ok { + lm.l.Errorf("Failed to read response info from context, got %v", r.Context().Value("response_info")) + responseInfo = defaultResponseInfo + } + method := r.Method + route := r.RequestURI + currentTime := time.Now().UTC() + httpVersion := r.Proto + + clientIP, _, err := net.SplitHostPort(r.RemoteAddr) + if err != nil { + lm.l.Errorf("Failed to read remote IP: %s", err.Error()) + clientIP = "unknown" + } + + lm.l.Infof(`%s - [%s] "%s %s %s" %d %d`, clientIP, currentTime.Format(time.RFC3339), method, route, httpVersion, responseInfo.ReturnCode, responseInfo.ContentLength) +} diff --git a/polyculeconnect/middlewares/middlewarechain.go b/polyculeconnect/middlewares/middlewarechain.go new file mode 100644 index 0000000..ac5070d --- /dev/null +++ b/polyculeconnect/middlewares/middlewarechain.go @@ -0,0 +1,23 @@ +package middlewares + +import ( + "net/http" + + "github.com/sirupsen/logrus" +) + +type MiddlewareChains struct { + handlers []http.Handler +} + +func (mc *MiddlewareChains) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + for _, h := range mc.handlers { + h.ServeHTTP(rw, r) + } +} + +func WithLogger(handler http.Handler, l *logrus.Logger) *MiddlewareChains { + return &MiddlewareChains{ + handlers: []http.Handler{handler, &LoggerMiddleware{l}}, + } +} diff --git a/polyculeconnect/robots.txt b/polyculeconnect/robots.txt new file mode 100644 index 0000000..e69de29 diff --git a/polyculeconnect/server/server.go b/polyculeconnect/server/server.go index 381ec94..d57d9a6 100644 --- a/polyculeconnect/server/server.go +++ b/polyculeconnect/server/server.go @@ -8,19 +8,23 @@ import ( "net/http" "os" - "git.faercol.me/faercol/polyculeconnect/template/config" + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/config" + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/controller/ui" + "git.faercol.me/faercol/polyculeconnect/polyculeconnect/middlewares" + dex_server "github.com/dexidp/dex/server" "github.com/sirupsen/logrus" ) type Server struct { - ctx context.Context - cancel context.CancelFunc - httpSrv *http.Server - listener net.Listener - serverMode config.ListeningMode - address string - handler *http.ServeMux - l *logrus.Logger + ctx context.Context + cancel context.CancelFunc + httpSrv *http.Server + listener net.Listener + serverMode config.ListeningMode + address string + handler *http.ServeMux + controllers map[string]http.Handler + l *logrus.Logger } func newUnixListener(sockPath string) (net.Listener, error) { @@ -38,7 +42,7 @@ func newUnixListener(sockPath string) (net.Listener, error) { return sock, nil } -func New(appConf *config.AppConfig, logger *logrus.Logger) (*Server, error) { +func New(appConf *config.AppConfig, dexSrv *dex_server.Server, logger *logrus.Logger) (*Server, error) { var listener net.Listener var addr string var err error @@ -59,6 +63,12 @@ func New(appConf *config.AppConfig, logger *logrus.Logger) (*Server, error) { panic(fmt.Errorf("unexpected listening mode %v", appConf.ServerMode)) } + controllers := map[string]http.Handler{ + ui.StaticRoute: &ui.StaticController{}, + "/": middlewares.WithLogger(dexSrv, logger), + // "/": middlewares.WithLogger(ui.NewIndexController(logger), logger), + } + m := http.NewServeMux() return &Server{ @@ -66,15 +76,19 @@ func New(appConf *config.AppConfig, logger *logrus.Logger) (*Server, error) { httpSrv: &http.Server{ Handler: m, }, - listener: listener, - l: logger, - serverMode: appConf.ServerMode, - address: addr, + listener: listener, + l: logger, + serverMode: appConf.ServerMode, + address: addr, + controllers: controllers, + ctx: context.TODO(), }, nil } func (s *Server) initMux() { - s.handler.HandleFunc("/", s.statusHandler) + for r, c := range s.controllers { + s.handler.Handle(r, c) + } } func (s *Server) Run(ctx context.Context) { @@ -96,12 +110,3 @@ func (s *Server) Run(ctx context.Context) { func (s *Server) Done() <-chan struct{} { return s.ctx.Done() } - -func (s *Server) statusHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { - w.WriteHeader(http.StatusMethodNotAllowed) - return - } - - w.Write([]byte("Hello world!")) -} diff --git a/polyculeconnect/templates/approval.html b/polyculeconnect/templates/approval.html new file mode 100644 index 0000000..e69de29 diff --git a/polyculeconnect/templates/complete.html b/polyculeconnect/templates/complete.html new file mode 100644 index 0000000..e8752cb --- /dev/null +++ b/polyculeconnect/templates/complete.html @@ -0,0 +1,14 @@ + + + + + + + +

It works!

+

+ Token is {{.Token}} +

+ + + \ No newline at end of file diff --git a/polyculeconnect/templates/device.html b/polyculeconnect/templates/device.html new file mode 100644 index 0000000..e69de29 diff --git a/polyculeconnect/templates/device_success.html b/polyculeconnect/templates/device_success.html new file mode 100644 index 0000000..e69de29 diff --git a/polyculeconnect/templates/error.html b/polyculeconnect/templates/error.html new file mode 100644 index 0000000..4a9acbe --- /dev/null +++ b/polyculeconnect/templates/error.html @@ -0,0 +1,8 @@ +{{ template "header.html" . }} + +
+

{{ .ErrType }}

+

{{ .ErrMsg }}

+
+ +{{ template "footer.html" . }} \ No newline at end of file diff --git a/polyculeconnect/templates/footer.html b/polyculeconnect/templates/footer.html new file mode 100644 index 0000000..cefcdb1 --- /dev/null +++ b/polyculeconnect/templates/footer.html @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/polyculeconnect/templates/header.html b/polyculeconnect/templates/header.html new file mode 100644 index 0000000..7999d2b --- /dev/null +++ b/polyculeconnect/templates/header.html @@ -0,0 +1,18 @@ + + + + + + + {{ issuer }} + + + + +
+
+ +
+
+ +
\ No newline at end of file diff --git a/polyculeconnect/templates/index.html b/polyculeconnect/templates/index.html new file mode 100644 index 0000000..556d339 --- /dev/null +++ b/polyculeconnect/templates/index.html @@ -0,0 +1,15 @@ + + + + + + + +
+
+ +
+
+ + + \ No newline at end of file diff --git a/polyculeconnect/templates/login.html b/polyculeconnect/templates/login.html new file mode 100644 index 0000000..3f905d5 --- /dev/null +++ b/polyculeconnect/templates/login.html @@ -0,0 +1,15 @@ +{{ template "header.html" . }} + +
+

Log in to {{ issuer }}

+
+ {{ range $c := .Connectors }} +
+ '{{ $c.ID }}' + {{ $c.Name }} +
+ {{ end }} +
+
+ +{{ template "footer.html" . }} \ No newline at end of file diff --git a/polyculeconnect/templates/oob.html b/polyculeconnect/templates/oob.html new file mode 100644 index 0000000..e69de29 diff --git a/polyculeconnect/templates/password.html b/polyculeconnect/templates/password.html new file mode 100644 index 0000000..e69de29 diff --git a/template/Makefile b/template/Makefile deleted file mode 100644 index 16349ff..0000000 --- a/template/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -.PHONY: build test - -build: - go build -o build/ - -test: - go test -v ./... - -run: build - ./build/template diff --git a/template/config/config.go b/template/config/config.go deleted file mode 100644 index 01ab09e..0000000 --- a/template/config/config.go +++ /dev/null @@ -1,109 +0,0 @@ -package config - -import ( - "encoding/json" - "errors" - "fmt" - "io/fs" - "os" - - "github.com/sirupsen/logrus" -) - -type ListeningMode int64 - -func (lm ListeningMode) String() string { - mapping := map[ListeningMode]string{ - ModeNet: "net", - ModeUnix: "unix", - } - val := mapping[lm] - return val -} - -func listeningModeFromString(rawVal string) (ListeningMode, error) { - mapping := map[string]ListeningMode{ - "unix": ModeUnix, - "net": ModeNet, - } - if typedVal, ok := mapping[rawVal]; !ok { - return ModeNet, fmt.Errorf("invalid listening mode %s", rawVal) - } else { - return typedVal, nil - } -} - -const ( - ModeUnix ListeningMode = iota - ModeNet -) - -type jsonConf struct { - Log struct { - Level string `json:"level"` - } `json:"log"` - Server struct { - Host string `json:"host"` - Port int `json:"port"` - Mode string `json:"mode"` - SockPath string `json:"sock"` - } `json:"server"` -} - -type AppConfig struct { - LogLevel logrus.Level - ServerMode ListeningMode - Host string - Port int - SockPath string -} - -func parseLevel(lvlStr string) logrus.Level { - for _, lvl := range logrus.AllLevels { - if lvl.String() == lvlStr { - return lvl - } - } - return logrus.InfoLevel -} - -func (ac *AppConfig) UnmarshalJSON(data []byte) error { - var jsonConf jsonConf - if err := json.Unmarshal(data, &jsonConf); err != nil { - return fmt.Errorf("failed to read JSON: %w", err) - } - ac.LogLevel = parseLevel(jsonConf.Log.Level) - - lm, err := listeningModeFromString(jsonConf.Server.Mode) - if err != nil { - return fmt.Errorf("failed to parse server listening mode: %w", err) - } - ac.ServerMode = lm - ac.SockPath = jsonConf.Server.SockPath - ac.Host = jsonConf.Server.Host - ac.Port = jsonConf.Server.Port - return nil -} - -var defaultConfig AppConfig = AppConfig{ - LogLevel: logrus.InfoLevel, - ServerMode: ModeNet, - Host: "0.0.0.0", - Port: 5000, -} - -func New(filepath string) (*AppConfig, error) { - content, err := os.ReadFile(filepath) - if err != nil { - if errors.Is(err, fs.ErrNotExist) { - conf := defaultConfig - return &conf, nil - } - return nil, fmt.Errorf("failed to read config file %q: %w", filepath, err) - } - var conf AppConfig - if err := json.Unmarshal(content, &conf); err != nil { - return nil, fmt.Errorf("failed to parse config file: %w", err) - } - return &conf, nil -} diff --git a/template/config/config_test.go b/template/config/config_test.go deleted file mode 100644 index 7088e2d..0000000 --- a/template/config/config_test.go +++ /dev/null @@ -1,137 +0,0 @@ -package config - -import ( - "os" - "path" - "testing" - - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" -) - -func TestListeningModeString(t *testing.T) { - assert.Equal(t, "net", ModeNet.String(), "Unexpected string value") - assert.Equal(t, "unix", ModeUnix.String(), "Unexpected string value") -} - -// Test returning a default config when providing a path that does not exist -func TestDefault(t *testing.T) { - conf, err := New("/this/path/does/not/exist") - if assert.Nil(t, err, "Unexpected error") { - assert.Equal(t, defaultConfig, *conf, "Unexpected config") - } -} - -// Test creating a valid config (net mode) -func TestOKNet(t *testing.T) { - tmpPath := t.TempDir() - content := `{ - "log": { - "level": "error" - }, - "server": { - "mode": "net", - "host": "127.0.0.1", - "port": 8888 - } -}` - confPath := path.Join(tmpPath, "config.json") - require.Nil(t, os.WriteFile(confPath, []byte(content), 0o644), "Failed to write config") - - expectedConf := AppConfig{ - LogLevel: logrus.ErrorLevel, - ServerMode: ModeNet, - Host: "127.0.0.1", - Port: 8888, - } - conf, err := New(confPath) - if assert.Nil(t, err, "Unexpected error") { - assert.Equal(t, expectedConf, *conf, "Unexpected config") - } -} - -// Test creating a valid config (unix mode) -func TestOKUnix(t *testing.T) { - tmpPath := t.TempDir() - content := `{ - "log": { - "level": "error" - }, - "server": { - "mode": "unix", - "sock": "/run/toto.sock" - } -}` - confPath := path.Join(tmpPath, "config.json") - require.Nil(t, os.WriteFile(confPath, []byte(content), 0o644), "Failed to write config") - - expectedConf := AppConfig{ - LogLevel: logrus.ErrorLevel, - ServerMode: ModeUnix, - SockPath: "/run/toto.sock", - } - conf, err := New(confPath) - if assert.Nil(t, err, "Unexpected error") { - assert.Equal(t, expectedConf, *conf, "Unexpected config") - } -} - -// Test creating a valid config, no log level provided, should be info -func TestOKNoLogLevel(t *testing.T) { - tmpPath := t.TempDir() - content := `{ - "server": { - "mode": "net", - "host": "127.0.0.1", - "port": 8888 - } -}` - confPath := path.Join(tmpPath, "config.json") - require.Nil(t, os.WriteFile(confPath, []byte(content), 0o644), "Failed to write config") - - expectedConf := AppConfig{ - LogLevel: logrus.InfoLevel, - ServerMode: ModeNet, - Host: "127.0.0.1", - Port: 8888, - } - conf, err := New(confPath) - if assert.Nil(t, err, "Unexpected error") { - assert.Equal(t, expectedConf, *conf, "Unexpected config") - } -} - -// Test giving an invalid server mode -func TestErrMode(t *testing.T) { - tmpPath := t.TempDir() - content := `{ - "log": { - "level": "error" - }, - "server": { - "mode": "toto", - "sock": "/run/toto.sock" - } -}` - confPath := path.Join(tmpPath, "config.json") - require.Nil(t, os.WriteFile(confPath, []byte(content), 0o644), "Failed to write config") - - _, err := New(confPath) - if assert.Error(t, err, "Unexpected nil error") { - errMsg := "failed to parse config file: failed to parse server listening mode: invalid listening mode toto" - assert.Equal(t, errMsg, err.Error(), "Unexpected error message") - } -} - -func TestInvalidJSON(t *testing.T) { - tmpPath := t.TempDir() - content := "toto" - confPath := path.Join(tmpPath, "config.json") - require.Nil(t, os.WriteFile(confPath, []byte(content), 0o644), "Failed to write config") - _, err := New(confPath) - if assert.Error(t, err, "Unexpected nil error") { - errMsg := "failed to parse config file: invalid character 'o' in literal true (expecting 'r')" - assert.Equal(t, errMsg, err.Error(), "Unexpected error message") - } -} diff --git a/template/go.mod b/template/go.mod deleted file mode 100644 index c2a73ab..0000000 --- a/template/go.mod +++ /dev/null @@ -1,15 +0,0 @@ -module git.faercol.me/faercol/go-mod-template/template - -go 1.20 - -require ( - github.com/sirupsen/logrus v1.9.3 - github.com/stretchr/testify v1.7.0 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect -) diff --git a/template/go.sum b/template/go.sum deleted file mode 100644 index 9243c28..0000000 --- a/template/go.sum +++ /dev/null @@ -1,16 +0,0 @@ -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -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/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/template/logger/logger.go b/template/logger/logger.go deleted file mode 100644 index 31b8a0e..0000000 --- a/template/logger/logger.go +++ /dev/null @@ -1,10 +0,0 @@ -package logger - -import "github.com/sirupsen/logrus" - -var L *logrus.Logger - -func Init(level logrus.Level) { - L = logrus.New() - L.SetLevel(level) -} diff --git a/template/main.go b/template/main.go deleted file mode 100644 index 5ef4d49..0000000 --- a/template/main.go +++ /dev/null @@ -1,76 +0,0 @@ -package main - -import ( - "context" - "flag" - "os" - "os/signal" - "time" - - "git.faercol.me/faercol/go-mod-template/template/config" - "git.faercol.me/faercol/go-mod-template/template/logger" - "git.faercol.me/faercol/go-mod-template/template/server" -) - -const stopTimeout = 10 * time.Second - -type cliArgs struct { - configPath string -} - -func parseArgs() *cliArgs { - configPath := flag.String("config", "", "Path to the JSON configuration file") - - flag.Parse() - - return &cliArgs{ - configPath: *configPath, - } -} - -func main() { - args := parseArgs() - - mainCtx, cancel := context.WithCancel(context.Background()) - - conf, err := config.New(args.configPath) - if err != nil { - panic(err) - } - - logger.Init(conf.LogLevel) - logger.L.Infof("Initialized logger with level %v", conf.LogLevel) - - logger.L.Info("Initializing server") - s, err := server.New(conf, logger.L) - if err != nil { - logger.L.Fatalf("Failed to initialize server: %s", err.Error()) - } - - go s.Run(mainCtx) - - c := make(chan os.Signal, 1) - signal.Notify(c, os.Interrupt) - - logger.L.Info("Application successfully started") - - logger.L.Debug("Waiting for stop signal") - select { - case <-s.Done(): - logger.L.Fatal("Unexpected exit from server") - case <-c: - logger.L.Info("Stopping main application") - cancel() - } - - logger.L.Debugf("Waiting %v for all daemons to stop", stopTimeout) - select { - case <-time.After(stopTimeout): - logger.L.Fatalf("Failed to stop all daemons in the expected time") - case <-s.Done(): - logger.L.Info("web server successfully stopped") - } - - logger.L.Info("Application successfully stopped") - os.Exit(0) -} diff --git a/template/server/server.go b/template/server/server.go deleted file mode 100644 index 9b9ac5b..0000000 --- a/template/server/server.go +++ /dev/null @@ -1,107 +0,0 @@ -package server - -import ( - "context" - "errors" - "fmt" - "net" - "net/http" - "os" - - "git.faercol.me/faercol/go-mod-template/template/config" - "github.com/sirupsen/logrus" -) - -type Server struct { - ctx context.Context - cancel context.CancelFunc - httpSrv *http.Server - listener net.Listener - serverMode config.ListeningMode - address string - handler *http.ServeMux - l *logrus.Logger -} - -func newUnixListener(sockPath string) (net.Listener, error) { - if err := os.Remove(sockPath); err != nil && !errors.Is(err, os.ErrNotExist) { - return nil, fmt.Errorf("failed to cleanup previously existing socket: %w", err) - } - - sock, err := net.Listen("unix", sockPath) - if err != nil { - return nil, fmt.Errorf("failed to create unix socket: %w", err) - } - if err := os.Chmod(sockPath, 0o777); err != nil { - return nil, fmt.Errorf("failed to set permissions to unix socket: %w", err) - } - return sock, nil -} - -func New(appConf *config.AppConfig, logger *logrus.Logger) (*Server, error) { - var listener net.Listener - var addr string - var err error - switch appConf.ServerMode { - case config.ModeNet: - addr = fmt.Sprintf("%s:%d", appConf.Host, appConf.Port) - listener, err = net.Listen("tcp", addr) - if err != nil { - return nil, fmt.Errorf("failed to init server in net mode: %w", err) - } - case config.ModeUnix: - addr = appConf.SockPath - listener, err = newUnixListener(appConf.SockPath) - if err != nil { - return nil, fmt.Errorf("failed to init server in unix mode: %w", err) - } - default: - panic(fmt.Errorf("unexpected listening mode %v", appConf.ServerMode)) - } - - m := http.NewServeMux() - - return &Server{ - handler: m, - httpSrv: &http.Server{ - Handler: m, - }, - listener: listener, - l: logger, - serverMode: appConf.ServerMode, - address: addr, - }, nil -} - -func (s *Server) initMux() { - s.handler.HandleFunc("/", s.statusHandler) -} - -func (s *Server) Run(ctx context.Context) { - s.ctx, s.cancel = context.WithCancel(ctx) - s.initMux() - switch s.serverMode { - case config.ModeNet: - s.l.Infof("Server listening on host %q", s.address) - case config.ModeUnix: - s.l.Infof("Server listening on unix socket %q", s.address) - default: - } - if err := s.httpSrv.Serve(s.listener); err != nil { - s.l.Errorf("failed to serve HTTP server: %s", err.Error()) - } - s.cancel() -} - -func (s *Server) Done() <-chan struct{} { - return s.ctx.Done() -} - -func (s *Server) statusHandler(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { - w.WriteHeader(http.StatusMethodNotAllowed) - return - } - - w.Write([]byte("Hello world!")) -}