From 0336971ef2390a36d5aa245752cd00d96f2697ad Mon Sep 17 00:00:00 2001 From: Ondrej Ezr Date: Fri, 3 May 2024 21:05:09 +0200 Subject: [PATCH] feat(HMS-3416): Switch to service accounts for dev auth For developement we have been using basic auth to authenticate against stage services. This switches the auth to Service accounts. --- config/api.env.example | 24 +++++++----- go.mod | 3 ++ go.sum | 23 ++++------- internal/config/config.go | 27 +++++++------ internal/config/helpers.go | 5 ++- internal/headers/access_token.go | 66 ++++++++++++++++++++++++++++++++ internal/headers/headers.go | 40 ++++++++++--------- 7 files changed, 130 insertions(+), 58 deletions(-) create mode 100644 internal/headers/access_token.go diff --git a/config/api.env.example b/config/api.env.example index 15de1a56..bc5ae9f2 100644 --- a/config/api.env.example +++ b/config/api.env.example @@ -140,30 +140,36 @@ # how often to cleanup the reservation (default "1h") # RESERVATION_LIFETIME int64 # how old reservation should be deleted, default equal to 365 days (default "8760h") -# REST_ENDPOINTS_IMAGE_BUILDER_PASSWORD string +# REST_ENDPOINTS_IMAGE_BUILDER_CLIENT_ID string # image builder credentials (dev only) (default "") +# REST_ENDPOINTS_IMAGE_BUILDER_CLIENT_SECRET string +# image builder credentials (dev only) (default "") +# REST_ENDPOINTS_IMAGE_BUILDER_ISSUER string +# sources issuer (default "https://sso.stage.redhat.com/auth/realms/redhat-external") # REST_ENDPOINTS_IMAGE_BUILDER_PROXY_URL string # proxy URL (dev only) (default "") # REST_ENDPOINTS_IMAGE_BUILDER_URL string # image builder URL (default "") -# REST_ENDPOINTS_IMAGE_BUILDER_USERNAME string -# image builder credentials (dev only) (default "") -# REST_ENDPOINTS_RBAC_PASSWORD string +# REST_ENDPOINTS_RBAC_CLIENT_ID string +# RBAC credentials (dev only) (default "") +# REST_ENDPOINTS_RBAC_CLIENT_SECRET string # RBAC credentials (dev only) (default "") +# REST_ENDPOINTS_RBAC_ISSUER string +# sources issuer (default "https://sso.stage.redhat.com/auth/realms/redhat-external") # REST_ENDPOINTS_RBAC_PROXY_URL string # proxy URL (dev only) (default "") # REST_ENDPOINTS_RBAC_URL string # RBAC URL (default "") -# REST_ENDPOINTS_RBAC_USERNAME string -# RBAC credentials (dev only) (default "") -# REST_ENDPOINTS_SOURCES_PASSWORD string +# REST_ENDPOINTS_SOURCES_CLIENT_ID string +# sources credentials (dev only) (default "") +# REST_ENDPOINTS_SOURCES_CLIENT_SECRET string # sources credentials (dev only) (default "") +# REST_ENDPOINTS_SOURCES_ISSUER string +# sources issuer (default "https://sso.stage.redhat.com/auth/realms/redhat-external") # REST_ENDPOINTS_SOURCES_PROXY_URL string # proxy URL (dev only) (default "") # REST_ENDPOINTS_SOURCES_URL string # sources URL (default "") -# REST_ENDPOINTS_SOURCES_USERNAME string -# sources credentials (dev only) (default "") # REST_ENDPOINTS_TRACE_DATA bool # open telemetry HTTP context pass and trace (default "true") # SENTRY_DSN string diff --git a/go.mod b/go.mod index c8f1bf30..a63a777a 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/iam v1.31.2 github.com/aws/aws-sdk-go-v2/service/sts v1.28.4 github.com/aws/smithy-go v1.20.1 + github.com/coreos/go-oidc v2.2.1+incompatible github.com/exaring/otelpgx v0.5.4 github.com/georgysavva/scany/v2 v2.1.0 github.com/getkin/kin-openapi v0.123.0 @@ -133,6 +134,7 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/pquerna/cachecontrol v0.2.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.48.0 // indirect github.com/prometheus/procfs v0.12.0 // indirect @@ -160,5 +162,6 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240308144416-29370a3891b7 // indirect google.golang.org/grpc v1.62.1 // indirect google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/square/go-jose.v2 v2.6.0 // indirect olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect ) diff --git a/go.sum b/go.sum index 85099844..16cce797 100644 --- a/go.sum +++ b/go.sum @@ -42,15 +42,12 @@ github.com/Unleash/unleash-client-go/v4 v4.1.0 h1:+9ZMa4sb176nlPfZyWYlWHeY8bA3od github.com/Unleash/unleash-client-go/v4 v4.1.0/go.mod h1:jzGQjqMwJm2y+vaVLzq3IzZPvh5SRWco0MNIw2KK03I= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= github.com/archdx/zerolog-sentry v1.8.2 h1:zS8n0+H7SsG161RN8dP47CSsdyrhODdo9LEDOPXJhXI= github.com/archdx/zerolog-sentry v1.8.2/go.mod h1:XrFHGe1CH5DQk/XSySu/IJSi5C9XR6+zpc97zVf/c4c= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go-v2 v1.25.3 h1:xYiLpZTQs1mzvz5PaI6uR0Wh57ippuEthxS4iK5v0n0= -github.com/aws/aws-sdk-go-v2 v1.25.3/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I= github.com/aws/aws-sdk-go-v2 v1.26.0 h1:/Ce4OCiM3EkpW7Y+xUnfAFpchU78K7/Ug01sZni9PgA= github.com/aws/aws-sdk-go-v2 v1.26.0/go.mod h1:35hUlJVYd+M++iLI3ALmVwMOyRYMmRqUXpTtRGW+K9I= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.1 h1:gTK2uhtAPtFcdRRJilZPx8uJLL2J85xK11nKtWL0wfU= @@ -100,6 +97,8 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL 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/cockroachdb/cockroach-go/v2 v2.2.0 h1:/5znzg5n373N/3ESjHF5SMLxiW4RKB05Ql//KWfeTFs= +github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= +github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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= @@ -132,7 +131,6 @@ github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNIT github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -173,7 +171,6 @@ github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaC github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -245,16 +242,12 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 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/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= @@ -279,11 +272,8 @@ github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= @@ -306,6 +296,8 @@ 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/pquerna/cachecontrol v0.2.0 h1:vBXSNuE5MYP9IJ5kjsdo8uq+w41jSPgvba2DEnkRx9k= +github.com/pquerna/cachecontrol v0.2.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI= github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU= github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k= @@ -324,7 +316,6 @@ github.com/redis/go-redis/v9 v9.5.1 h1:H1X4D3yHPaYrkL5X06Wh6xNVM/pX0Ft4RV0vMGvLB github.com/redis/go-redis/v9 v9.5.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/riandyrn/otelchi v0.5.1 h1:0/45omeqpP7f/cvdL16GddQBfAEmZvUyl2QzLSE6uYo= github.com/riandyrn/otelchi v0.5.1/go.mod h1:ZxVxNEl+jQ9uHseRYIxKWRb3OY8YXFEu+EkNiiSNUEA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0= @@ -347,6 +338,7 @@ github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/ 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= 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= @@ -478,7 +470,6 @@ 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= -golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -516,15 +507,15 @@ google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGm google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/h2non/gock.v1 v1.0.10 h1:D4j796HhgidcxF0LnDyFXcoEbEZWoLEWf0kRh61p22w= gopkg.in/h2non/gock.v1 v1.0.10/go.mod h1:KHI4Z1sxDW6P4N3DfTWSEza07YpkQP7KJBfglRMEjKY= +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/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/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.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/config/config.go b/internal/config/config.go index e9d2d736..0849e145 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -121,22 +121,25 @@ var config struct { } `env-prefix:"PROMETHEUS_"` RestEndpoints struct { RBAC struct { - URL string `env:"URL" env-default:"" env-description:"RBAC URL"` - Username string `env:"USERNAME" env-default:"" env-description:"RBAC credentials (dev only)"` - Password string `env:"PASSWORD" env-default:"" env-description:"RBAC credentials (dev only)"` - Proxy proxy `env-prefix:"PROXY_" env-description:"RBAC HTTP proxy (dev only)"` + URL string `env:"URL" env-default:"" env-description:"RBAC URL"` + Issuer string `env:"ISSUER" env-default:"https://sso.stage.redhat.com/auth/realms/redhat-external" env-description:"sources issuer"` + ClientID string `env:"CLIENT_ID" env-default:"" env-description:"RBAC credentials (dev only)"` + ClientSecret string `env:"CLIENT_SECRET" env-default:"" env-description:"RBAC credentials (dev only)"` + Proxy proxy `env-prefix:"PROXY_" env-description:"RBAC HTTP proxy (dev only)"` } `env-prefix:"RBAC_"` ImageBuilder struct { - URL string `env:"URL" env-default:"" env-description:"image builder URL"` - Username string `env:"USERNAME" env-default:"" env-description:"image builder credentials (dev only)"` - Password string `env:"PASSWORD" env-default:"" env-description:"image builder credentials (dev only)"` - Proxy proxy `env-prefix:"PROXY_" env-description:"image builder HTTP proxy (dev only)"` + URL string `env:"URL" env-default:"" env-description:"image builder URL"` + Issuer string `env:"ISSUER" env-default:"https://sso.stage.redhat.com/auth/realms/redhat-external" env-description:"sources issuer"` + ClientID string `env:"CLIENT_ID" env-default:"" env-description:"image builder credentials (dev only)"` + ClientSecret string `env:"CLIENT_SECRET" env-default:"" env-description:"image builder credentials (dev only)"` + Proxy proxy `env-prefix:"PROXY_" env-description:"image builder HTTP proxy (dev only)"` } `env-prefix:"IMAGE_BUILDER_"` Sources struct { - URL string `env:"URL" env-default:"" env-description:"sources URL"` - Username string `env:"USERNAME" env-default:"" env-description:"sources credentials (dev only)"` - Password string `env:"PASSWORD" env-default:"" env-description:"sources credentials (dev only)"` - Proxy proxy `env-prefix:"PROXY_" env-description:"sources HTTP proxy (dev only)"` + URL string `env:"URL" env-default:"" env-description:"sources URL"` + Issuer string `env:"ISSUER" env-default:"https://sso.stage.redhat.com/auth/realms/redhat-external" env-description:"sources issuer"` + ClientID string `env:"CLIENT_ID" env-default:"" env-description:"sources credentials (dev only)"` + ClientSecret string `env:"CLIENT_SECRET" env-default:"" env-description:"sources credentials (dev only)"` + Proxy proxy `env-prefix:"PROXY_" env-description:"sources HTTP proxy (dev only)"` } `env-prefix:"SOURCES_"` TraceData bool `env:"TRACE_DATA" env-default:"true" env-description:"open telemetry HTTP context pass and trace"` } `env-prefix:"REST_ENDPOINTS_"` diff --git a/internal/config/helpers.go b/internal/config/helpers.go index 37980392..ed20fe9e 100644 --- a/internal/config/helpers.go +++ b/internal/config/helpers.go @@ -119,8 +119,9 @@ func DumpConfig(logger zerolog.Logger) { configCopy.AWS.Key = replacement configCopy.AWS.Secret = replacement configCopy.AWS.Session = replacement - configCopy.RestEndpoints.Sources.Password = replacement - configCopy.RestEndpoints.ImageBuilder.Password = replacement + configCopy.RestEndpoints.RBAC.ClientSecret = replacement + configCopy.RestEndpoints.Sources.ClientSecret = replacement + configCopy.RestEndpoints.ImageBuilder.ClientSecret = replacement configCopy.Azure.ClientID = replacement configCopy.Azure.ClientSecret = replacement configCopy.GCP.JSON = replacement diff --git a/internal/headers/access_token.go b/internal/headers/access_token.go new file mode 100644 index 00000000..6141b312 --- /dev/null +++ b/internal/headers/access_token.go @@ -0,0 +1,66 @@ +package headers + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + "strings" + + "github.com/coreos/go-oidc" + "github.com/rs/zerolog" +) + +type tokenResponse struct { + AccessToken string `json:"access_token"` + Scope string `json:"scope"` +} + +const ( + scopes = "openid api.iam.service_accounts" + grant_type = "client_credentials" +) + +// https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token" -d "scope=openid api.iam.service_accounts +func getToken(ctx context.Context, issuerUrl, clientId, clientSecret string) (string, error) { + provider, err := oidc.NewProvider(ctx, issuerUrl) + if err != nil { + return "", fmt.Errorf("failed to fetch oidc provider info: %w", err) + } + + data := url.Values{} + data.Add("grant_type", grant_type) + data.Add("scope", scopes) + data.Add("client_id", clientId) + data.Add("client_secret", clientSecret) + + req, err := http.NewRequestWithContext(ctx, http.MethodPost, provider.Endpoint().TokenURL, strings.NewReader(data.Encode())) + if err != nil { + return "", fmt.Errorf("failed to form request: %w", err) + } + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + req.Header.Add("Content-Length", strconv.Itoa(len(data.Encode()))) + res, err := http.DefaultClient.Do(req) + if err != nil { + return "", fmt.Errorf("failed to request a token: %w", err) + } + defer res.Body.Close() + + token := tokenResponse{} + body, err := io.ReadAll(res.Body) + if err != nil { + return "", fmt.Errorf("failed to parse a token response: %w", err) + } + + err = json.Unmarshal(body, &token) + if err != nil { + return "", fmt.Errorf("failed to parse a token response: %w", err) + } + + zerolog.Ctx(ctx).Debug().Msgf("Fetched access token: %s", token.AccessToken) + + return token.AccessToken, nil +} diff --git a/internal/headers/headers.go b/internal/headers/headers.go index 4fe067fb..853acab6 100644 --- a/internal/headers/headers.go +++ b/internal/headers/headers.go @@ -2,7 +2,6 @@ package headers import ( "context" - "encoding/base64" "net/http" "github.com/RHEnVision/provisioning-backend/internal/config" @@ -11,15 +10,15 @@ import ( "github.com/rs/zerolog" ) -func basicAuth(username, password string) string { - auth := username + ":" + password - return base64.StdEncoding.EncodeToString([]byte(auth)) -} - -func addIdentityHeader(ctx context.Context, req *http.Request, username, password string) error { - if username != "" && password != "" { - zerolog.Ctx(ctx).Warn().Msgf("Username/password authentication: %s", username) - req.Header.Add("Authorization", "Basic "+basicAuth(username, password)) +func addIdentityHeader(ctx context.Context, req *http.Request, issuerUrl, clientID, clientSecret string) error { + if clientID != "" && clientSecret != "" { + zerolog.Ctx(ctx).Warn().Msgf("Using service account authentication: %s", clientID) + token, err := getToken(ctx, issuerUrl, clientID, clientSecret) + if err != nil { + zerolog.Ctx(ctx).Error().Err(err).Msg("Fetching access token failed") + return err + } + req.Header.Add("Authorization", "Bearer "+token) } else { logger := zerolog.Ctx(ctx) logger.Trace().Str("identity", identity.GetIdentityHeader(ctx)).Msg("HTTP client identity set") @@ -37,19 +36,22 @@ func AddEdgeRequestIdHeader(ctx context.Context, req *http.Request) error { } func AddSourcesIdentityHeader(ctx context.Context, req *http.Request) error { - username := config.Sources.Username - password := config.Sources.Password - return addIdentityHeader(ctx, req, username, password) + issuerUrl := config.Sources.Issuer + clientID := config.Sources.ClientID + clientSecret := config.Sources.ClientSecret + return addIdentityHeader(ctx, req, issuerUrl, clientID, clientSecret) } func AddImageBuilderIdentityHeader(ctx context.Context, req *http.Request) error { - username := config.ImageBuilder.Username - password := config.ImageBuilder.Password - return addIdentityHeader(ctx, req, username, password) + issuerUrl := config.ImageBuilder.Issuer + clientID := config.ImageBuilder.ClientID + clientSecret := config.ImageBuilder.ClientSecret + return addIdentityHeader(ctx, req, issuerUrl, clientID, clientSecret) } func AddRbacIdentityHeader(ctx context.Context, req *http.Request) error { - username := config.RBAC.Username - password := config.RBAC.Password - return addIdentityHeader(ctx, req, username, password) + issuerUrl := config.RBAC.Issuer + clientID := config.RBAC.ClientID + clientSecret := config.RBAC.ClientSecret + return addIdentityHeader(ctx, req, issuerUrl, clientID, clientSecret) }