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

Support for SAML as a Silo IdP, part 1 #994

Closed
wants to merge 58 commits into from

Conversation

jmpesp
Copy link
Contributor

@jmpesp jmpesp commented Apr 29, 2022

Add the db schemas, models, and some endpoints to support configuring a
SAML IdP for a Silo. Enough functionality is here to support the first
step of SP-initiated SAML login flow. More work is required to support
receiving the SAML IdP's response, and actually creating and logging in
the user.

Two tables were added here: one that relates a silo to a list of typed
identity providers, and one for saml configuration. Future work will add
"local" and "ldap" identity provider support.

Table column order was corrected - I didn't see any bugs from this but
am aware that the bug potential exists.

Currently, the external-authenticator role only applies to the
default silo, not any new ones. Making that opctx work with any silo
will unlock some more testing.

This commit also moves the unauthorized_coverage code into the
unauthorized function, and sets up both hardcoded and new non-hardcoded
data. When global images support was added, a hardcoded port was used
for the httptest server and it was a problem to find an unused port, but
allowing for non-hardcoded data means any port can be used.

Add the db schemas, models, and some endpoints to support configuring a
SAML IdP for a Silo. Enough functionality is here to support the first
step of SP-initiated SAML login flow. More work is required to support
receiving the SAML IdP's response, and actually creating and logging in
the user.

Two tables were added here: one that relates a silo to a list of typed
identity providers, and one for saml configuration. Future work will add
"local" and "ldap" identity provider support.

Table column order was corrected - I didn't see any bugs from this but
am aware that the bug potential exists.

Currently, the external-authenticator role only applies to the
default silo, not any new ones. Making that opctx work with any silo
will unlock some more testing.

This commit also moves the unauthorized_coverage code into the
unauthorized function, and sets up both hardcoded and new non-hardcoded
data. When global images support was added, a hardcoded port was used
for the httptest server and it was a problem to find an unused port, but
allowing for non-hardcoded data means any port can be used.
@jmpesp
Copy link
Contributor Author

jmpesp commented Apr 29, 2022

Looks like everything's failing because xmlsec1 isn't installed. Looking into it.

nexus/src/db/model.rs Outdated Show resolved Hide resolved
nexus/src/db/model.rs Outdated Show resolved Hide resolved
nexus/src/db/model.rs Outdated Show resolved Hide resolved
)*
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

👌

@davepacheco
Copy link
Collaborator

Is xmlsec1 something that's now expected to be installed on the build/deployment machine and we depend on it at build and run time (similar to libpq, etc.)? In that case, I think you want to update the install_prerequisites script and not add new steps to the GitHub/buildomat workflows. I say that because those workflows won't be run on individuals' machines, whereas the install_prerequisites script is intended to be run by devs and it's also run in CI so it should cover all cases and actually gets tested regularly.

@david-crespo
Copy link
Contributor

We couldn't confirm that install_prerequisites.sh was run on CI, where is that?

@davepacheco
Copy link
Collaborator

Dang, I had thought #870 already landed. I think maybe we want to land that?

@jmpesp
Copy link
Contributor Author

jmpesp commented Apr 29, 2022

Unfortunately, there's also no xmlsec1 packages for helios.

EDIT: or OmniOS

@jmpesp
Copy link
Contributor Author

jmpesp commented May 2, 2022

Unfortunately, there's also no xmlsec1 packages for helios.

xmlsec1 does build on helios. the following completes ok:

git clone https://github.com/lsh123/xmlsec
cd xmlsec/
pfexec pkg install pkg:/developer/build/libtool pkg:/library/libtool/libltdl
./autogen.sh
gmake -j $(nproc)

Paging @jclulow - how do packages get built for helios? Is this something I can do?

@jclulow
Copy link
Collaborator

jclulow commented May 3, 2022

Unfortunately, there's also no xmlsec1 packages for helios.
Paging @jclulow - how do packages get built for helios? Is this something I can do?

It's still a bit manual, so I've gone ahead and written the recipe and published the package for now. In the future, yes, I want things to be more self-service!

I took version 1.2.33 (latest stable) and built it into this package:

pkg://helios-dev/library/[email protected]:20220503T112921Z

You should be able to install that to get the libraries and the xmlsec(1) binary etc. The build recipe is in the garbage compactor.

@jmpesp
Copy link
Contributor Author

jmpesp commented May 3, 2022

@jclulow thanks for turning this around so quickly - I opened a PR in the garbage-compactor repo to address a dynamic loading problem with xmlsec, but once that's in it builds and runs on helios no problem.

@smklein what do you think about landing #870?

@smklein
Copy link
Collaborator

smklein commented May 4, 2022

@jclulow thanks for turning this around so quickly - I opened a PR in the garbage-compactor repo to address a dynamic loading problem with xmlsec, but once that's in it builds and runs on helios no problem.

@smklein what do you think about landing #870?

I just rebased #870 - should be ready to go now.

jmpesp added 15 commits May 6, 2022 13:54
remove silo_id from params, it was not used
add DerEncodedKeyPair type to add a bit of API safety

remove get prefix from functions

validate DER keys
Use serde's deserialize_with to validate public cert and private keys,
causing failure if the DerEncodedKeyPair isn't valid. The visitor used
here is a fn from `String -> Result<String>` which allows for early
validation, and afterwards any code operating on DerEncodedKeyPair can
be sure it contains valid data.

Unfortunately, the deserialize_with could not be a fn from `String ->
an openssl::type` because the openssl types do not derive JsonSchema.

Previously some of this validation was in SiloSamlIdentityProvider's
validate, and that has been removed in this commit.
Instead of putting an impl for the model::SiloSamlIdentityProvider type
into the authn subsystem, make a new authn type, and convert the model
type into that.

Move the logic that looks up SiloIdentityProviderType from nexus.rs to
authn silo subsystem.

Move validate function logic into a new TryFrom impl for the authn
SiloSamlIdentityProvider type. This way it's part of the conversion and
cannot be forgotten about.
Ran

    find */ -type f -exec sed -i -e 's/SiloIdentityProvider/IdentityProvider/g' {} + ;
    find */ -type f -exec sed -i -e 's/SILO_IDENTITY_PROVIDER/IDENTITY_PROVIDER/g' {} + ;
    find */ -type f -exec sed -i -e 's/silo_identity_provider/identity_provider/g' {} + ;
    find */ -type f -exec sed -i -e 's/SiloSamlIdentityProvider/SamlIdentityProvider/g' {} + ;
    find */ -type f -exec sed -i -e 's/SILO_SAML_IDENTITY_PROVIDER/SAML_IDENTITY_PROVIDER/g' {} + ;
    find */ -type f -exec sed -i -e 's/silo_saml_identity_provider/saml_identity_provider/g' {} + ;

and

    git mv ./nexus/src/db/model/silo_identity_provider.rs ./nexus/src/db/model/identity_provider.rs
// model to the authn type here, this is a server
// error: it was validated before it went into the
// DB.
omicron_common::api::external::Error::internal_error(&e.to_string())
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you add a tiny bit of context here (like maybe make that argument &format!("deserializing SAML IdP from database: {:#}", e)? I'm afraid if we ever hit this case it'll be very hard to tell what we were even trying to parse.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Definitely, context added in 46de770

@@ -397,7 +397,7 @@ impl<'a> Root<'a> {
lookup_resource! {
name = "Silo",
ancestors = [],
children = [ "Organization" ],
children = [ "Organization", "SiloIdentityProvider", "SiloSamlIdentityProvider" ],
Copy link
Collaborator

Choose a reason for hiding this comment

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

Okay. I think "backend" is consistent with its use in other distributed systems contexts (e.g., "backend task" in this SRE book chapter), but I'm definitely not attached to it!

@jmpesp
Copy link
Contributor Author

jmpesp commented May 25, 2022

There's too much going on in this PR, plus a lot has changed in main, PLUS even if I do rebase the whole thing it will remain blocked on Josh's PR upstreaming the "dynamic" branch of our samael fork. I'm going to close this, and break it up into several smaller PRs so the parts unrelated to the main SAML functionality can go in.

@jmpesp jmpesp closed this May 25, 2022
@jmpesp jmpesp deleted the silo_authn_providers branch May 25, 2022 14:15
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.

5 participants