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

rework configuration of the plugin #399

Merged
merged 1 commit into from
Sep 19, 2024
Merged

Conversation

jtnord
Copy link
Member

@jtnord jtnord commented Sep 16, 2024

The server configuration (token URLs, scopes etc) are now in separate describable, flags to contol setting of options is removed and is based on the actual option/type

This makes the UX marginally cleaner, but helps the backend code to not need flags to know if something is set.

The configuration format is backwards compatible with previous versions, but the casc format is not.

⚠️The behaviour of overriding scopes in "auto" merge has changed. If override scopes is set then those scopes are used unconditionally. Previously the scopes where only used if they where also advertised, but this did not make sense as the provider is not required to advertise all the scopes it supported. This is a change in behaviour, but should not be breaking as we will only end up request more scopes, which the server should ignore if they are unsupported.

⚠️Users of casc will need to adapt their configuration.

configuration of the provider side has been moved into a serverConfiguration section and split to 2 different types wellKnown for configuration via a auto discovery and manual for manual configuration.

e.g.

for manual configuration:

  securityRealm:
    oic:
      serverConfiguration:
        manual:
          authorizationServerUrl: https://url.example.com/authorize
          jwksServerUrl: https://jwks.example.com/jwks
          tokenAuthMethod: client_secret_post
          tokenServerUrl: https://token.example.com/token
          scopes: scopes

and for auto configuration:


  securityRealm:
    oic:
      serverConfiguration:
        wellKnown:
          wellKnownOpenIDConfigurationUrl: https://idp.example.com:/someRealm/.well-known/openid-configuration
Screen Shots

Before

image

image

After

image

image

image

Testing done

  • run some local tests against an IDP configured with a well-known endpoint.
  • saved a manual config and manually inspected the config.xml
  • ran mvn verify locally

Submitter checklist

  • Make sure you are opening from a topic/feature/bugfix branch (right side) and not your main branch!
  • Ensure that the pull request title represents the desired changelog entry
  • Please describe what you did
  • Link to relevant issues in GitHub or Jira
  • Link to relevant pull requests, esp. upstream and downstream changes
  • Ensure you have provided tests - that demonstrates feature works or fixes the issue

@jtnord jtnord force-pushed the refactor-config branch 2 times, most recently from ae8f74a to 276c6b8 Compare September 16, 2024 16:57
Comment on lines +9 to +12
<f:radioBlock title="${%Basic}" name="tokenAuthMethod"
checked="${instance.tokenAuthMethod == 'client_secret_basic'}" value="client_secret_basic" inline="true" help="${null}"/>
<f:radioBlock title="${%Post}" name="tokenAuthMethod"
checked="${instance.tokenAuthMethod == null || instance.tokenAuthMethod == 'client_secret_post'}" value="client_secret_post" inline="true" help="${null}"/>
Copy link
Member Author

Choose a reason for hiding this comment

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

the previous did not have help=${null} but it was added here as they did (prior to the change and with this change before help=${null]) actually render with a help button, but the help was unrelated to the option.

@jtnord jtnord force-pushed the refactor-config branch 2 times, most recently from 0a585d0 to c2ef3e6 Compare September 16, 2024 17:49
Comment on lines +9 to +12
<f:radioBlock title="${%Basic}" name="tokenAuthMethod"
checked="${instance.tokenAuthMethod == 'client_secret_basic'}" value="client_secret_basic" inline="true" help="${null}"/>
<f:radioBlock title="${%Post}" name="tokenAuthMethod"
checked="${instance.tokenAuthMethod == null || instance.tokenAuthMethod == 'client_secret_post'}" value="client_secret_post" inline="true" help="${null}"/>
Copy link
Member Author

Choose a reason for hiding this comment

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

set the default here for new installs with the == null check (slightly fewer clicks for the defaults)

@@ -0,0 +1,4 @@
<div>
Recommended. json webtoken key signature url of the openid connect provider
Copy link
Member Author

Choose a reason for hiding this comment

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

original had Recommended. jswon webtoken which is fixed here and causing this not to show as a rename

@jtnord jtnord marked this pull request as ready for review September 16, 2024 17:55
@jtnord jtnord requested a review from a team as a code owner September 16, 2024 17:55
@jtnord jtnord marked this pull request as draft September 16, 2024 17:56
@jtnord jtnord marked this pull request as ready for review September 17, 2024 11:33
@jtnord jtnord force-pushed the refactor-config branch 2 times, most recently from 4cdb879 to 9799c0b Compare September 17, 2024 11:42
pom.xml Outdated
@@ -49,6 +49,7 @@
<spotless.check.skip>false</spotless.check.skip>
<spotbugs.effort>Max</spotbugs.effort>
<configuration-as-code.version>1836.vccda_4a_122a_a_e</configuration-as-code.version>
<hpi.compatibleSinceVersion>4.431</hpi.compatibleSinceVersion>
Copy link
Member Author

@jtnord jtnord Sep 17, 2024

Choose a reason for hiding this comment

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

config is migrated, but the Jenkins config-as-code format is no longer compatable, so noting so users get a warning before updating.

Will need updating if anything gets merged before this

Copy link

codecov bot commented Sep 17, 2024

Codecov Report

Attention: Patch coverage is 77.02703% with 51 lines in your changes missing coverage. Please review.

Project coverage is 76.03%. Comparing base (c0be63e) to head (3e8cbca).
Report is 9 commits behind head on master.

Files with missing lines Patch % Lines
...i/plugins/oic/OicServerWellKnownConfiguration.java 73.33% 24 Missing and 4 partials ⚠️
...va/org/jenkinsci/plugins/oic/OicSecurityRealm.java 72.34% 7 Missing and 6 partials ⚠️
...nsci/plugins/oic/OicServerManualConfiguration.java 85.50% 9 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #399      +/-   ##
============================================
+ Coverage     72.47%   76.03%   +3.55%     
- Complexity      244      259      +15     
============================================
  Files            12       15       +3     
  Lines          1021     1043      +22     
  Branches        148      149       +1     
============================================
+ Hits            740      793      +53     
+ Misses          201      174      -27     
+ Partials         80       76       -4     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Boolean useRefreshTokens)
Secret clientSecret,
OicServerConfiguration serverConfiguration,
Boolean disableSslVerification)
Copy link
Member Author

Choose a reason for hiding this comment

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

for a future refactoring, given this is a Boolean it is obvious that this should not be a required field and moved to a @DataboundSetter

Comment on lines -372 to -378
try {
Field field = getClass().getDeclaredField("endSessionEndpoint");
field.setAccessible(true);
field.set(this, endSessionUrl + "/");
} catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
LOGGER.log(Level.SEVERE, "Can't set endSessionEndpoint from old value", e);
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I could see no need for reflection here - the field is available so we can just use it directly.

}
}
} catch (FormException e) {
// FormException does not override toString() so looses info on the fields set and the message may not have
Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -421,28 +458,9 @@ public Secret getClientSecret() {
return clientSecret == null ? Secret.fromString(NO_SECRET) : clientSecret;
}

public String getWellKnownOpenIDConfigurationUrl() {
Copy link
Member Author

Choose a reason for hiding this comment

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

there are no reported OSS plugins or known private plugins that depend on this plugin, so the only backwards compatibility we need to worry about is the config.xml migration

OicSecurityRealm.UsingDefaultScopes = Using ''openid email''.
OicSecurityRealm.RUSureOpenIdNotInScope = Are you sure you don''t want to include ''openid'' as an scope?
OicSecurityRealm.RUSureOpenIdNotInScope = Are you sure you don''t want to include ''openid'' as a scope?
OicSecurityRealm.ScopesRequired = Scopes is required.
Copy link
Member Author

Choose a reason for hiding this comment

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

sounds like bad English, but "scopes" is the field, not a plural of "scope" so the field is singular.
Probably should be reworded so that it has something other than just "the field is required"

@@ -3,19 +3,21 @@ OicLogoutAction.OicLogout = Oic Logout
OicSecurityRealm.DisplayName = Login with Openid Connect
OicSecurityRealm.ClientIdRequired = Client id is required.
OicSecurityRealm.ClientSecretRequired = Client secret is required.
OicSecurityRealm.URLNotAOpenIdEnpoint = URL does seem to describe OpenID Connect endpoints
OicSecurityRealm.URLNotAOpenIdEnpoint = URL does not seem to describe OpenID Connect endpoints
Copy link
Member Author

Choose a reason for hiding this comment

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

unrelated, but noticed this was wrong when moving the tests.

OicSecurityRealm.NotAValidURL = Not a valid url.
OicSecurityRealm.CouldNotRetreiveWellKnownConfig = Could not retrieve well-known config {0,number,integer} {1}
OicSecurityRealm.CouldNotParseResponse = Could not parse response
OicSecurityRealm.ErrorRetreivingWellKnownConfig = Error when retrieving well-known config
OicSecurityRealm.TokenServerURLKeyRequired = Token Server Url Key is required.
OicSecurityRealm.TokenAuthMethodRequired = Token auth method is required.
OicSecurityRealm.UsingDefaultUsername = Using ''sub''.
OicSecurityRealm.UsingDefaultScopes = Using ''openid email''.
OicSecurityRealm.RUSureOpenIdNotInScope = Are you sure you don''t want to include ''openid'' as an scope?
OicSecurityRealm.RUSureOpenIdNotInScope = Are you sure you don''t want to include ''openid'' as a scope?
Copy link
Member Author

Choose a reason for hiding this comment

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

unrelated, but noticed this when moving the tests.

@jtnord jtnord mentioned this pull request Sep 18, 2024
6 tasks
mikecirioli
mikecirioli previously approved these changes Sep 18, 2024
new OicServerWellKnownConfiguration(wellKnownOpenIDConfigurationUrl);
conf.setScopesOverride(this.overrideScopes);
serverConfiguration = conf;
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

consider making this else into an explicit if to protect against future changes? if the expected values of automanualconfigure ever change and this is not updated then you would get the default case even when you don't want it

Copy link
Member Author

Choose a reason for hiding this comment

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

The field is dead from this version onward so there would be no issues with it changing in future.

Just here for the readRosolve and is transient so it's either "auto"``"manual" or null

The server configuration (token URLs, scopes etc) are now in separate
describable.

This makes the UX cleaner, and the code cleaner in the realm.

The config.xml is backwards compatable with previous versions, but the casc
format is not.

when in discovery mode via well known endpoint the override scopes are
now used explicitly rather than using the overlapping scopes from the
overrides and those provided by the server
@jtnord jtnord merged commit 289bd3f into jenkinsci:master Sep 19, 2024
20 checks passed
@jtnord jtnord deleted the refactor-config branch September 19, 2024 10:31
private transient LocalDateTime wellKnownExpires = null;

@DataBoundConstructor
public OicServerWellKnownConfiguration(String wellKnownOpenIDConfigurationUrl) {
Copy link
Member

Choose a reason for hiding this comment

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

JCasC wise you would normally drop the class prefix so this field would be called openIDConfigurationUrl as its already in a well known configuration class the well known bit is implied

That way you don't get the double wellKnown in the yaml:

securityRealm:
    oic:
      serverConfiguration:
        wellKnown:
          openIDConfigurationUrl: [https://idp.example.com:/someRealm/.well-known/openid-configuration](https://idp.example.com/someRealm/.well-known/openid-configuration)

Copy link
Member Author

@jtnord jtnord Sep 19, 2024

Choose a reason for hiding this comment

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

is there a way to do this with an annotation so that the config.xml format stays the same or is the only choice now to fix this to use a custom piece of code(at which point I think it may be better to live with it)?

Copy link
Member Author

Choose a reason for hiding this comment

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

@Symbol only works on types (enum, class, interfaces) not on fields or methods, so I will bear this in mind for any future work, but am not planning on adding another data migration at this time.

Copy link
Member

Choose a reason for hiding this comment

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

Sure readResolve would be the normal approach, there's no alias via annotation.

@jimsnab
Copy link

jimsnab commented Oct 4, 2024

@jtnord could you update the docs?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants