-
Notifications
You must be signed in to change notification settings - Fork 204
Legend Authentication
This doc is a proposal for refactoring the Legend metamodel (and related impl detail) wrto authentication.
- Many ways to do the same thing - A concept can be described in many ways. This increases cognitive load for users and also duplication of Legend code and effort.
In both cases a private key is loaded from a vault ; though there are some differences.
Class AwsPKAuthenticationStrategy extends AuthenticationStrategy
{
secretArn: String[1];
user: String[1];
}
Class SnowflakePublicAuthenticationStrategy extends AuthenticationStrategy
{
privateKeyVaultReference : String[1];
passPhraseVaultReference : String[1];
publicUserName : String[1];
}
-
Reusable components buried in specific modules The SnowflakePublicAuthenticationStrategy can be used by any component that needs to obtain an encrypted private key. But using this strategy requires adding a dependency on the relational module.
-
No consistent way to describe authn Any Legend component that connects to an external "data source" needs some form of authentication. While there might be many data sources there are a relatively small number of authentication schemes that (I think) can be consistently described and used across the platform.
-
Split authentication from credential acquisition Authentication is the process by which a system verifies the identity of a "user". E.g a database authenticates the user making a connection.
Authentication requires that "user" present one/more "credentials". Credentials might be explicitly acquired (e.g read a key/pair from a vault) or might be acquired from the runtime environment (e.g current Kerberos subject).
To complete authentication, credentials have to be presented to the target system using some protocol. E.g add credentials to a JDBC properties object, create a file on disk that can be read by the ODBC driver, add a HTTP header with a bearer token etc.
While the authentication protocol by itself is very data source specific, the credential acquisition is more general and can be reused.
- Identify a grammar to consistently describe credential acquisition
- Identify a grammar to consistently describe credential acquisition in the context of a connection
- Define metamodels for 1 and 2. Add Maven modules to legend-engine for 1 and 2
- Implement reusable credential acquisition code and add to legend-engine as a Maven module.
- We might not find the perfect abstraction. Very specific authn impls should be housed where they are used.
- Authn is relatively heavy in terms of Java library dependencies. How can we prevent these dependencies from leaking all over the place ? For e.g should we shade/relocate all third party dependencies ?
- Other projects that use Legend need to be able to extend credential acquisition behavior. At the minimum they should be able to define and load their own implementations.
- How can we make the new metamodel coexist with the old metatmodel, migration path etc.
A few sketches.
Relational.
# Current
RelationalDatabaseConnection my::conn
{
store: my::store,
type: Snowflake,
specification: Snowflake {
name: db1,
account1: account1,
},
auth: SnowflakePublic {
userName: a
privateKeyVaultReference: b
privateKeyPassPhraseVaultReference: c
}
}
# Proposed
RelationalDatabaseConnection my::conn
{
store: my::store,
type: Snowflake,
specification: Snowflake {
name: db1,
account1: account1,
},
auth: [ <-------------------- auth schemes supported by this connection
SnowflakePublic { <------ on auth scheme
userName: a
privateKey: PrivateKeyCredential { <----------- credential
vault: aws/secretsmanager
reference: arn:1234
}
passPhrase: PlainTextCredential{
vault: aws/secretsmanager
reference: arn:4567
}
}
]
}
Service store.
Current
ServiceStoreConnection my::conn
{
store: my::store,
baseUrl: http://data.com
}
Proposed
ServiceStoreConnection my::conn
{
store: my::store,
baseUrl: http://data.com,
auth: [ <-------- service store is a little tricky. Unlike Relational, ServiceStore declares the "schemes" it supports. The auth model needs to carry enough metadata that we can validate if a configured auth is supported by the ServiceStore
{
GSSSO {},
mTLS {
clientKeyStore : JavaKeyStoreCredential {
keyStorePath : /local/certs/api1.jks
},
caKeyStore: JavaKeyStoreCredential {
keyStorePath : /local/certs/ca.jks
}
},
APIKey {
key : myKey
value : PlainTextCredential {
vault: aws/secretsmanager,
reference : arn:1234
}
}
}
]
}
Persistence
Mastery
https://github.com/epsstan/legend-engine/tree/generic-authn/legend-engine-xt-credentials
- For Legend Users
- For Legend Maintainers