- Description
- Setup - The basics of getting started with auth0
- Usage - Managing Auth0
- Usage - Querying Auth0
- Limitations - OS compatibility, etc.
- License and Authorship
- Development - Guide for contributing to the module
This module allows you to use Puppet to manage your Auth0 entities. It also provides the ability to query Auth0 and retrieve credentials for use in Machine-to-Machine authentication flows (which you can then write to an application configuration file).
In order for Puppet to access Auth0, you will need to create a Machine-to-Machine Application (aka a non_interactive
client) inside Auth0,
and grant that client access to the Auth0 Management API. See Machine-to-Machine Applications
for details. The scopes used by each resource type and function are documented in REFERENCE.md.
This module treats each Auth0 tenant as a remote 'device', and uses the puppet device
pattern for managing Auth0 resources. See the
Puppet Device Documentation for details. The easiest way to get started is to use
the puppetlabs-device_manager module, like so:
device_manager { 'my-tenant.auth0.com':
type => 'auth0_tenant',
credentials => {
client_id => $management_client_id,
client_secret => $management_client_secret,
domain => 'my-tenant.auth0.com',
},
}
The proxy node that is running puppet device
will need to have the auth0 gem installed. The easiest way to set this up is
to use the puppet_gem
provider for the package
resource type:
package { 'auth0':
ensure => '4.11.0',
provider => 'puppet_gem',
}
To use the auth0_get_client_credentials
function you will also need the auth0 gem installed on the Puppet Server. The easiest way to set this up is
with the puppetlabs-puppetserver_gem module:
package { 'auth0':
ensure => present,
provider => 'puppetserver_gem',
}
If you are using this module with Puppet 5, you will need to have access to the puppet-resource_api
gem
on both your server and agents. You can either do this via package
resources with the puppet_gem
and puppetserver_gem
types as above, or use the
puppetlabs-resource_api
module to do it for you.
These resource types can be used in a Device context to manage resources via the Auth0 Management API
auth0_client { 'example_application':
display_name => 'Example Application',
description => 'An example application to show how to use the auth0 Puppet module.',
app_type => 'non_interactive',
callbacks => ['https://app.example.com/callback'],
allowed_origins => ['https://app.example.com'],
web_origins => ['https://app.example.com'],
}
For Clients, the resource title will be stored in the client_metadata
as puppet_resource_identifier
.
If you pass keep_extra_callbacks => true
, then callbacks defined in Auth0 but not in Puppet will be retained; otherwise they will be removed.
This is useful for dev/test tenants in which individual developers may add callbacks on localhost through the dashboard. keep_extra_allowed_origins
,
keep_extra_web_origins
and keep_extra_logout_urls
function similarly.
auth0_resource_server { 'https://api.example.com':
display_name => "Example API",
signing_alg => "RS256",
scopes => {
'read:thingies' => 'Get information about Thingies',
'write:thingies' => 'Create, update and destroy Thingies',
'read:doodads' => 'Get information about Doodads',
},
}
auth0_client_grant { 'Give Example Application access to Example API':
client_resource => 'example_application',
audience => 'https://api.example.com':,
scopes => [
'read:thingies',
],
}
# Equivalent to above
auth0_client_grant { 'example_application -> https://api.example.com':
scopes => [
'read:thingies',
],
}
auth0_rule { 'Example Rule':
script => file('profile/auth0/example_rule.js'),
}
auth0_connection { 'ExampleConnection':
clients => [
'example_application',
'another_application',
],
options => {
brute_force_protection => true,
mfa => {
active => true,
return_enroll_settings => true,
},
},
strategy => 'auth0',
}
If you pass keep_extra_clients => true
, then clients assigned to that
connection in Auth0 but not in Puppet will be retained; otherwise they will be
removed. keep_extra_options
behaves similarly. However, in either case these
only have an effect if you specify a value for the clients
or options
attributes, respectively; omitting those attributes entirely will leave them
untouched.
keep_extra_options
performs a non-recursive merge between the options stored
in Auth0 and the options you specify; nested hashes such as the mfa
hash in
the example above will be overwritten even with keep_extra_options
, if you
provide a value for them.
The auth0_get_client_credentials
auth0_get_client_credentials_by_name
functions can be used in an Agent or Apply context to retrieve information from
Auth0 when configuring your own servers and applications.
auth0_get_client_credentials
looks up clients by their
puppet_resource_identifier, whereas auth0_get_client_credentials_by_name
looks them up by display name.
auth0::management_client_id: 'abcdef12345678'
auth0::management_client_secret: 'abcedfg12313fgasdt235gargq345qrg4423425413543254535'
auth0::tenant_domain: 'example.auth0.com'
$credentials = auth0_get_client_credentials('example_application')
file { '/etc/example.conf':
ensure => present,
content => epp('profile/example/example.conf.epp', {
client_id => $credentials['client_id'],
client_secret => $credentials['client_secret'],
}),
}
$credentials = auth0_get_client_credentials(
'example_application',
'abcdef12345678',
'abcedfg12313fgasdt235gargq345qrg4423425413543254535',
'example.auth0.com',
)
file { '/etc/example.conf':
ensure => present,
content => epp('profile/example/example.conf.epp', {
client_id => $credentials['client_id'],
client_secret => $credentials['client_secret'],
}),
}
In order for Puppet to operate, every resource needs an identifier which meets two criteria:
- It uniquely identifies a specific resource, consistently over time.
- It can be specified by the sysadmin when creating the resource.
Most Auth0 resource types have a unique identifier which fails the second criterion: for example, the unique identifier for an
Auth0 Client resource should be its client_id
, but you can't specify the client_id when creating a resource, so it can't be used as a
namevar
in Puppet (and even if you could, you wouldn't really want to).
In order to work around this for clients we look for a field named puppet_resource_identifier
in the client's
client_metadata
hash, and use that as the namevar
. This attribute should be treated as unique and immutable,
even if auth0 doesn't force you to.
Rules don't have anything analogous to client_metadata
, so we're stuck using the rule's "Display Name" as a namevar.
Again, because of this you should treat Rule names as unique and immutable identifiers, even though Auth0 doesn't require you to.
auth0_resource_server
resources don't have this problem, since the identifier
(aka 'Audience') attribute of a Resource Server is
an immutable identifier that can be specified when creating the resource.
The ruby-auth0
gem (on which this module is built) doesn't expose enough information during rate-limiting to try dynamically wait out the issue. If rate-limiting
is encountered during the puppet run, then further resources which make use of the same API endpoints will fail. This module does do some caching to limit the number
of API requests.
Not all aspects of your Auth0 configuration can be managed via their API, not all resource types that can be managed by the API are implemented by this module yet, and not all properties of the implemented resource types are supported yet. Specifically, the following properties are not yet supported by this module:
- from the Clients API:
- allowed_clients
- jwt_configuration.scopes
- encryption_key
- cross_origin_auth
- cross_origin_loc
- custom_login_page_on
- custom_login_page
- custom_login_page_preview
- form_template
- is_heroku_app
- addons
- client_metadata (except for the puppet_resource_identifier)
- mobile
- from the ResourceServers API:
- verificationLocation
- options
This module was authored by Adam Gardner, and is Copyright (c) 2019 Magic Memories (USA) LLC.
It is distributed under the terms of the Apache-2.0 license; see the LICENSE file for details.
If you run into any problems, open an issue or fork and open a Pull Request.
To be able to run the spec suite during development, first install the necessary dependencies:
bundle install
Then, run the spec suite:
bundle exec rake spec