Open wccropper opened 2 years ago
Hi
This is possible using the kubernetesPodTemplateSpecPatches
field of the shinyproxy CRD. First you have to create a configmap containing the keystore. You can do this with a typical yaml file, or you can use kustomize for it:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
configMapGenerator:
- name: saml-keystore
files:
- shinyproxy-saml-keystore.jks
Next, you can mount the configmap into the ShinyProxy pod, using the kubernetesPodTemplateSpecPatches
field, for example:
apiVersion: openanalytics.eu/v1alpha1
kind: ShinyProxy
metadata:
name: shinyproxy
spec:
proxy:
title: Open Analytics Shiny Proxy
logo-url: https://www.openanalytics.eu/shinyproxy/logo.png
landing-page: /
heartbeat-rate: 10000
heartbeat-timeout: 60000
port: 8080
authentication: saml
saml:
keystore: /opt/shinyproxy/saml-keystore/keystore.jks
specs:
- id: 01_hello
display-name: Hello Application
description: Application which demonstrates the basics of a Shiny app
container-cmd: ["R", "-e", "shinyproxy::run_01_hello()"]
container-image: openanalytics/shinyproxy-demo
access-groups: [scientists, mathematicians]
- id: 06_tabsets
container-cmd: ["R", "-e", "shinyproxy::run_06_tabsets()"]
container-image: openanalytics/shinyproxy-demo
access-groups: scientists
kubernetesPodTemplateSpecPatches: |
- op: add
path: /spec/volumes/-
value:
name: saml-keystore
configMap:
name: saml-keystore
- op: add
path: /spec/containers/0/volumeMounts/-
value:
name: saml-keystore
mountPath: /opt/shinyproxy/saml-keystore/keystore.jks
subPath: shinyproxy-saml.jks
logging:
file:
name: shinyproxy.log
Currently this is not very well documented, therefore I'll keep this issue open to remind us of improving the documentation.
Thanks for this. I was unable to look at it until today and it doesn't seem to work. My config blocks look like:
spec:
proxy:
authentication: saml
saml:
idp-metadata-url: redacted
app-entity-id: redacted
app-base-url: redacted
roles-attribute: http://schemas.microsoft.com/ws/2008/06/identity/claims/role
logout-method: local
force-authn: true
keystore: /opt/shinyproxy/saml-keystore/keystore.jks
keystore-password: passwd
encryption-cert-name: shinyapps-saml-pem
kubernetesPodTemplateSpecPatches: |
- op: add
path: /spec/volumes/-
value:
name: saml-keystore
configMap:
name: saml-keystore
- op: add
path: /spec/containers/0/volumeMounts/-
value:
name: saml-keystore
mountPath: /opt/shinyproxy/saml-keystore/keystore.jks
subPath: shinyapps-saml-keystore.jks
The error block is:
2022-04-04 16:27:02.629 INFO 1 --- [ XNIO-2 task-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
2022-04-04 16:27:02.635 INFO 1 --- [ XNIO-2 task-1] o.s.s.s.m.MetadataGeneratorFilter : No default metadata configured, generating with default values, please pre-configure metadata for production use
2022-04-04 16:27:02.648 ERROR 1 --- [ XNIO-2 task-1] io.undertow.request : UT005023: Exception handling request to /actuator/health/liveness
java.lang.NullPointerException: null
at org.opensaml.xml.security.credential.KeyStoreCredentialResolver.resolveFromSource(KeyStoreCredentialResolver.java:127) ~[xmltooling-1.4.6.jar!/:na]
at org.opensaml.xml.security.credential.AbstractCriteriaFilteringCredentialResolver.resolve(AbstractCriteriaFilteringCredentialResolver.java:57) ~[xmltooling-1.4.6.jar!/:na]
at org.opensaml.xml.security.credential.AbstractCredentialResolver.resolveSingle(AbstractCredentialResolver.java:30) ~[xmltooling-1.4.6.jar!/:na]
at org.opensaml.xml.security.credential.AbstractCredentialResolver.resolveSingle(AbstractCredentialResolver.java:26) ~[xmltooling-1.4.6.jar!/:na]
at org.springframework.security.saml.key.JKSKeyManager.resolveSingle(JKSKeyManager.java:171) ~[spring-security-saml2-core-1.0.10.RELEASE.jar!/:1.0.10.RELEASE]
at org.springframework.security.saml.key.JKSKeyManager.getCredential(JKSKeyManager.java:191) ~[spring-security-saml2-core-1.0.10.RELEASE.jar!/:1.0.10.RELEASE]
at org.springframework.security.saml.metadata.MetadataGenerator.getServerKeyInfo(MetadataGenerator.java:205) ~[spring-security-saml2-core-1.0.10.RELEASE.jar!/:1.0.10.RELEASE]
at org.springframework.security.saml.metadata.MetadataGenerator.buildSPSSODescriptor(MetadataGenerator.java:329) ~[spring-security-saml2-core-1.0.10.RELEASE.jar!/:1.0.10.RELEASE]
at org.springframework.security.saml.metadata.MetadataGenerator.generateMetadata(MetadataGenerator.java:189) ~[spring-security-saml2-core-1.0.10.RELEASE.jar!/:1.0.10.RELEASE]
at org.springframework.security.saml.metadata.MetadataGeneratorFilter.processMetadataInitialization(MetadataGeneratorFilter.java:127) ~[spring-security-saml2-core-1.0.10.RELEASE.jar!/:1.0.10.RELEASE]
at org.springframework.security.saml.metadata.MetadataGeneratorFilter.doFilter(MetadataGeneratorFilter.java:86) ~[spring-security-saml2-core-1.0.10.RELEASE.jar!/:1.0.10.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.3.9.RELEASE.jar!/:5.3.9.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.3.9.RELEASE.jar!/:5.3.9.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.3.9.RELEASE.jar!/:5.3.9.RELEASE]
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:117) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46) ~[undertow-core-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60) ~[undertow-core-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43) ~[undertow-core-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.SendErrorPageHandler.handleRequest(SendErrorPageHandler.java:52) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43) ~[undertow-core-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99) ~[undertow-servlet-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:387) ~[undertow-core-2.2.8.Final.jar!/:2.2.8.Final]
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:841) ~[undertow-core-2.2.8.Final.jar!/:2.2.8.Final]
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35) ~[jboss-threads-3.1.0.Final.jar!/:3.1.0.Final]
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019) ~[jboss-threads-3.1.0.Final.jar!/:3.1.0.Final]
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558) ~[jboss-threads-3.1.0.Final.jar!/:3.1.0.Final]
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1423) ~[jboss-threads-3.1.0.Final.jar!/:3.1.0.Final]
at org.xnio.XnioWorker$WorkerThreadFactory$1$1.run(XnioWorker.java:1280) ~[xnio-api-3.8.4.Final.jar!/:3.8.4.Final]
at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
I have verified the jks is mounted and I can use keytool within the pod to access the cert.
Thoughts?
I see there are config options for the application.yaml for saml+jks. I am using Azure AD Enterprise application. The communication is working as I am prompted to login and the correct entity-id is being returned (firefox SAML_tracer). The current error is:
I believe I need to provide as java keystore of the saml signing cert from Azure. I have created this and stored it as a secret, but do no see a way to pass this to the sp-shinyproxy containers.