Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement auth #186

Merged
merged 3 commits into from
Sep 5, 2023
Merged

Implement auth #186

merged 3 commits into from
Sep 5, 2023

Conversation

setrofim
Copy link
Collaborator

Implement API authentication and authorization.

  • Define IAuthorizer interface that can be used to obtain a gin
    middleware handler that performs authorisation.
  • Add a mechanism to obtain an IAuthorizer for a particular role base on
    Veraison configuration.
  • Implement "passthrough" authorizer that duplicates existing behavior
    (no auth).
  • Implement "basic" authorizer that does not rely on an external
    authorization server.
  • Implement "keycloak" authorizer that uses Keycloak service for
    authentication.
  • Update provisioning service to authorize based on "provisioner" role.
  • Update management service to authorize based on "manager" role.
  • Add the previously missing README for the management service.

note: Once the corresponding client-side support for auth has been added, there will be additional changes to update the colci/ pocli inside the docker deployment.

auth/README.md Outdated Show resolved Hide resolved
auth/README.md Outdated Show resolved Hide resolved
auth/README.md Outdated Show resolved Hide resolved
auth/README.md Outdated Show resolved Hide resolved
auth/basic.go Outdated Show resolved Hide resolved
WORKDIR /opt/keycloak
# note: for development set up early; use proper certification in production.
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 \
-dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" \
Copy link
Collaborator

@yogeshbdeshpande yogeshbdeshpande Aug 30, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the server IP on line 6 be hard coded or read from yaml file?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nah, this isn't really used. This sets up keys used for the HTTPS cert, but we're enabling and using HTTP (specifically to avoid having to deal with certs in the test deployment). There isn't really a way to disable HTTPS (that I've seen), so the keys need to generated even if they're not used.

@@ -11,6 +11,7 @@ VTS_PORT ?= 50051
PROVISIONING_PORT ?= 8888
VERIFICATION_PORT ?= 8080
MANAGEMENT_PORT ?= 8088
KEYCLOAK_PORT ?= 11111
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought, this could be 8880 ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I specifically chose something different, since this isn't really part of Veraison -- this is an external service Veraison depends on (besides, its already difficult enough to remember the correct port to use for DEBUG_PORT, as they're all just 8's and 0's in various permutations).

@@ -73,8 +74,19 @@ func main() {
provisioner := provisioner.New(vtsClient)

log.Infow("initializing provisioning API service", "address", cfg.ListenAddr)
authorizer, err := auth.NewAuthorizer(subs["auth"], log.Named("auth"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Presumably if the Line 41 auth subs is missing the NewAuthroizer will default to passthrough ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

@yogeshbdeshpande yogeshbdeshpande left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some minor comments but in general LGTM!

@setrofim
Copy link
Collaborator Author

Comments addressed.

auth/README.md Outdated Show resolved Hide resolved
@setrofim setrofim force-pushed the setrofim-auth branch 2 times, most recently from 7330858 to 5949699 Compare August 31, 2023 14:04
Signed-off-by: Sergei Trofimov <[email protected]>
Copy link
Contributor

@thomas-fossati thomas-fossati left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

auth/basic.go Outdated
Comment on lines 108 to 109
c.Writer.Header().Set("WWW-Authenticate", "Basic realm=veraison")
c.AbortWithStatus(http.StatusUnauthorized)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(just a suggestion)

To make this a bit more user friendly (i.e., to let the user distinguish among the different 401 root causes) we could return a "problem details" payload like we do elsewhere.

(this would apply to all other 401 returns in this scope.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Will add that.

Incidentally, we really need to think about how we're organising our code. There is enough commonality between the different REST API (verification, provisioning, etc) implementations, such as the ReportProblem, that it would make sense to have a common place for the code, rather than duplicationg it for each API.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Will add that.

awesome

Incidentally, we really need to think about how we're organising our code. There is enough commonality between the different REST API (verification, provisioning, etc) implementations, such as the ReportProblem, that it would make sense to have a common place for the code, rather than duplicationg it for each API.

➕1

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raised #192

}

o.config = ginkeycloak.KeycloakConfig{
Url: fmt.Sprintf("http://%s:%s", cfg.Host, cfg.Port),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is quite security critical that the authoriser is authenticated.

(note to self: we need an issue for moving all the service endpoints to HTTPS.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(note to self: we need an issue for moving all the service endpoints to HTTPS.)

Added #191


// note: this mapper function will only be called once the JWT had
// alreadybeen verified by ginkeycloak, so extracting claims without
// verification here is, in fact, safe.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

paranoid mode on: have we checked that keycloak refuses JWTs with none algorithm?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haven't tried that, as the only way to easlily get a JWT than can be used for this is from keycloak it self. We can test it out at some point, but I would argue that is a security issue with keycloak.

I.e. it is somehting that needs to be tested and secured for a particular deployment, not withithin veraison code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[...] but I would argue that is a security issue with keycloak.

yes

BTW, timely (but yet to be answered) question: keycloak/keycloak#22744

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, yeah. Thanks for finding that. Upvoted and subscribed.

auth/keycloak.go Outdated Show resolved Hide resolved
deployments/docker/src/veraison-realm.json Outdated Show resolved Hide resolved
auth/basic.go Outdated Show resolved Hide resolved
Implement API authentication and authorization.

- Define IAuthorizer interface that can be used to obtain a gin
  middleware handler that performs authorisation.
- Add a mechanism to obtain an IAuthorizer for a particular role base on
  Veraison configuration.
- Implement "passthrough" authorizer that duplicates existing behavior
  (no auth).
- Implement "basic" authorizer that does not rely on an external
  authorization server.
- Implement "keycloak" authorizer that uses Keycloak service for
  authentication.
- Update provisioning service to authorize based on "provisioner" role.
- Update management service to authorize based on "manager" role.
- Add the previously missing README for the management service.

Signed-off-by: Sergei Trofimov <[email protected]>
- Update the deployment diagram to match current deployment. This
  includes diagramming the management service (was neglected when the
  service was added to the deployment).
- Update REAME text around the diagram to match current deployment.
- Add *.bkp to .gitignore. draw.io generates .bkp files when saving an
  updated diagram.

Signed-off-by: Sergei Trofimov <[email protected]>
@setrofim setrofim merged commit 992e533 into main Sep 5, 2023
9 checks passed
@setrofim setrofim deleted the setrofim-auth branch September 5, 2023 09:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants