diff --git a/charts/opserver/Chart.yaml b/charts/opserver/Chart.yaml index 6bee433f..b47a82ad 100644 --- a/charts/opserver/Chart.yaml +++ b/charts/opserver/Chart.yaml @@ -15,7 +15,7 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.0.1 +version: 1.0.13 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to diff --git a/charts/opserver/templates/deployment.yaml b/charts/opserver/templates/deployment.yaml index 3ea6d5a5..7c6e74d8 100644 --- a/charts/opserver/templates/deployment.yaml +++ b/charts/opserver/templates/deployment.yaml @@ -110,10 +110,49 @@ spec: secretKeyRef: name: {{ .Values.sqlExternalSecret.targetName }} key: exceptionalPassword + - name: Security__Provider + value: {{ .Values.opserverSettings.security.provider }} + +{{- if eq .Values.opserverSettings.security.provider "OIDC" }} + - name: Security__UseHttpsForRedirects + value: "true" + - name: Security__Name + value: "Okta" + - name: Security__ViewEverythingGroups + value: {{ .Values.opserverSettings.security.viewGroups | quote }} + - name: Security__AdminEverythingGroups + value: {{ .Values.opserverSettings.security.adminGroups | quote }} + - name: Security__ClientId + valueFrom: + secretKeyRef: + name: {{ .Values.opserverExternalSecret.targetName }} + key: oktaClientId + - name: Security__ClientSecret + valueFrom: + secretKeyRef: + name: {{ .Values.opserverExternalSecret.targetName }} + key: oktaClientSecret + - name: Security__AuthorizationUrl + value: "https://stackoverflow.okta.com/oauth2/v1/authorize" + - name: Security__AccessTokenUrl + value: "https://stackoverflow.okta.com/oauth2/v1/token" + - name: Security__UserInfoUrl + value: "https://stackoverflow.okta.com/oauth2/v1/userinfo" + - name: Security__NameClaim + value: "preferred_username" + - name: Security__GroupsClaim + value: "groups" + - name: Security__Scopes__0 + value: "email" + - name: Security__Scopes__1 + value: "groups" + - name: Security__Scopes__2 + value: "profile" +{{- end }} {{- if hasKey .Values.opserverSettings "sql" }} - name: Modules__Sql__defaultConnectionString - value: "Server=$(SQL_EXCEPTIONAL_SERVERNAME);Database=Local.Exceptions;User ID=$(SQL_USERNAME);Password=$(SQL_PASSWORD);" + value: "Server=$(SQL_EXCEPTIONAL_SERVERNAME);Database=master;User ID=$(SQL_USERNAME);Password=$(SQL_PASSWORD);" {{- range $i, $instance := .Values.opserverSettings.sql }} - name: Modules__Sql__instances__{{ $i }}__name value: "{{ $instance.name }}" diff --git a/charts/opserver/templates/opserver-secret.yaml b/charts/opserver/templates/opserver-secret.yaml new file mode 100644 index 00000000..6df7eef7 --- /dev/null +++ b/charts/opserver/templates/opserver-secret.yaml @@ -0,0 +1,18 @@ +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: {{ .Values.opserverExternalSecret.name }} +spec: + refreshInterval: {{ .Values.opserverExternalSecret.refreshInterval }} + secretStoreRef: + name: {{ .Values.opserverExternalSecret.storeRefName }} + kind: ClusterSecretStore + target: + name: {{ .Values.opserverExternalSecret.targetName }} + data: + - secretKey: oktaClientId + remoteRef: + key: {{ .Values.opserverExternalSecret.remoteRefs.oktaClientId }} + - secretKey: oktaClientSecret + remoteRef: + key: {{ .Values.opserverExternalSecret.remoteRefs.oktaClientSecret }} diff --git a/charts/opserver/values.yaml b/charts/opserver/values.yaml index d0d9c0ba..06a319c2 100644 --- a/charts/opserver/values.yaml +++ b/charts/opserver/values.yaml @@ -53,6 +53,15 @@ ingress: db: ExceptionalDbName: Local.Exceptions +opserverExternalSecret: + name: opserver-secret + refreshInterval: 5m + storeRefName: fakeopserversecretstore + targetName: opserver-secret + remoteRefs: + oktaClientId: opserver-okta-client-id + oktaClientSecret: opserver-okta-client-secret + sqlExternalSecret: name: opserver-sqldb-external-secret refreshInterval: 5m diff --git a/cnab/app/run.ps1 b/cnab/app/run.ps1 index 36af260e..fd99312c 100644 --- a/cnab/app/run.ps1 +++ b/cnab/app/run.ps1 @@ -163,15 +163,11 @@ switch ($action) { } sqlExternalSecret = @{ - name = "opserver-sqldb-external-secret" - refreshInterval = "5m" storeRefName = $vars.vars.secretStore - targetName = "sql-secret" - remoteRefs = @{ - exceptionalServerName = "ExceptionsSqlServerName" - exceptionalUsername = "db-opserver-User" - exceptionalPassword = "db-opserver-Password" - } + } + + opserverExternalSecret = @{ + storeRefName = $vars.vars.secretStore } opserverSettings = $vars.vars.opserverSettings diff --git a/cnab/app/variables.GCP.json b/cnab/app/variables.GCP.json index 22164e5c..ca5036e0 100644 --- a/cnab/app/variables.GCP.json +++ b/cnab/app/variables.GCP.json @@ -4,11 +4,11 @@ "product": "pubplat", "project": "opserver", "tenant": "sandbox", - "releaseTag": "pr-250" + "releaseTag": "pr-5" }, "runtime": { "cd": false, - "local": true, + "local": false, "name": "GCP" }, "tenant_metadata": { @@ -33,12 +33,18 @@ "isHADRPrimary": "true", "podDisruptionBudgetMinAvailable": "1", "opserverSettings": { + "hostUrl": "opserver.sandbox.int.gcp.stackoverflow.net", "sql": [ - { "name": "host.docker.internal" } + { "name": "db.db" } ], "exceptions": [ - { "serverName": "host.docker.internal" } - ] + { "serverName": "db.db", "database": "Dev.Exceptions" } + ], + "security": { + "adminGroups": "OpserverDev-Admin", + "viewGroups": "OpserverDev-View", + "provider": "OIDC" + } } } } \ No newline at end of file diff --git a/src/Opserver.Web/Controllers/AuthController.OIDC.cs b/src/Opserver.Web/Controllers/AuthController.OIDC.cs index e9087d48..0e0b2b81 100644 --- a/src/Opserver.Web/Controllers/AuthController.OIDC.cs +++ b/src/Opserver.Web/Controllers/AuthController.OIDC.cs @@ -27,6 +27,21 @@ partial class AuthController private const string OidcIdentifierKey = "id"; private const string OidcReturnUrlKey = "returnUrl"; + private string GetRedirectUri() + { + var oidcSettings = (OIDCSecuritySettings) Current.Security.Settings; + var scheme = (oidcSettings.UseHttpsForRedirects ? "https" : Request.Scheme); + var redirectUri = Url.Action( + nameof(OAuthCallback), + ControllerContext.ActionDescriptor.ControllerName, + null, + scheme, + Request.Host.Value, + null + ); + return redirectUri; + } + [AllowAnonymous] [HttpGet("login/oauth/callback")] public async Task OAuthCallback(string code, string state, string error = null) @@ -74,14 +89,7 @@ public async Task OAuthCallback(string code, string state, string // hooray! we're all set, let's go fetch our access token var oidcSettings = (OIDCSecuritySettings) Current.Security.Settings; var scopes = oidcSettings.Scopes ?? OIDCSecuritySettings.DefaultScopes; - var redirectUri = Url.Action( - nameof(OAuthCallback), - ControllerContext.ActionDescriptor.ControllerName, - null, - Request.Scheme, - Request.Host.Value, - null - ); + var redirectUri = GetRedirectUri(); var form = new NameValueCollection { @@ -216,14 +224,7 @@ private IActionResult RedirectToProvider(string returnUrl) }); var oidcSettings = (OIDCSecuritySettings) Current.Security.Settings; - var redirectUri = Url.Action( - nameof(OAuthCallback), - ControllerContext.ActionDescriptor.ControllerName, - null, - Request.Scheme, - Request.Host.Value, - null - ); + var redirectUri = GetRedirectUri(); // construct the URL to the authorization endpoint var authorizationUrl = new UriBuilder(oidcSettings.AuthorizationUrl); diff --git a/src/Opserver.Web/Security/OIDCSecuritySettings.cs b/src/Opserver.Web/Security/OIDCSecuritySettings.cs index ae4ee5ca..e1840898 100644 --- a/src/Opserver.Web/Security/OIDCSecuritySettings.cs +++ b/src/Opserver.Web/Security/OIDCSecuritySettings.cs @@ -46,5 +46,10 @@ public class OIDCSecuritySettings : SecuritySettings /// Gets or sets the name of the "name" claim. /// public string GroupsClaim { get; set; } = "groups"; + + /// + /// When redirecting to an OIDC provider, whether to always use https for the redirect/referral. + /// + public bool UseHttpsForRedirects { get; set; } = false; } }