Cognito & Okta authentication for Kibana

Katie Gamanji
Product and Engineering at Condé Nast
6 min readJun 24, 2019

--

At Condé Nast International we use multiple open source tools to solutionize networking, monitoring, logging, authentication and many more. We use Fluentd, AWS ElasticSearch and Kibana for log collection, storage, indexing, and visualization. However, our recent challenge was the integration of Okta as an identity provider for Kibana authentication.

Full logging stack at Condé Nast International

In this blog post, my aim is to provide an overview of Condé Nast International’s approach to role-based access for Kibana by using Cognito with Okta SAML integration.

The Theoretical

Cognito

Cognito is the AWS service that provides authentication, authorization and user management for applications. It is composed of 2 main parts:

  • user pools — user directory management. It will also be configured with a domain name.
  • identity pools — for provisioning temporary access to AWS services

Once a user pool, identity pool and domain name are configured, Cognito can be enabled for the authentication of different AWS services (e.g. ElastiSearch, S3, DynamoDB). For example, enabling Cognito for Kibana will trigger the creation of an app client that will be linked to the identity pool by default.

In this blog post, I will not deep-dive into the set up of a user or identity pool, as there are a great number of guides that tackle this issue. However, it is worth to mention that at Condé Nast International we use Terraform for Cognito setup.

Okta

Okta is a widely spread identity provider for application authentication and user management. At Condé Nast International, Okta is integrated with active directory (AD).

Okta can be linked to Cognito with SAML since Cognito supports SAML as an external federated identity provider.

AWS ElasticSearch

AWS ElasticSearch is a service for log ingestion and storage. It is an easily scalable and highly available service that is capable to handle log indexing under load, without service disruption.

Every ElasticSearch domain has an addon for Kibana (for log visualization) and supports Cognito authentication. In further sections of this blog, it will be assumed that Cognito authentication is enabled for Kibana. Consequently, this means that an app client is already set up and integrated with Cognito identity pool.

The Practical

In this section, I will provide details on how we configured Cognito and Okta as a mechanism for Kibana sign-in.

Okta configuration

As mentioned previously, a SAML 2.0 application will need to be configured in Okta. Here is a highlight of the main attributes that are required:

  • Single sign on URL — assertion consumer endpoint to the SAML identity provider. It will be the Cognito URL domain name followed by saml2/idpresponse (e.g. https://kibana.auth.eu-central-1.amazoncognito.com/saml2/idpresponse)
  • Audience URI — service provider entity ID or urn of the user pool (e.g.
    urn:amazon:cognito:sp:eu_central-1_abcdefgi)
  • Attribute statements — configuration for any required attributes by the user pool. In this example, an email claim is configured in the SAML assertion (e.g.
    http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress to user.email value)
  • Group attributes statements — exposing specific groups using regex for filtering function. In this case, we target the SAML assertion to include groups that start with cognito_. These groups will be used later on to provide role-based access to Kibana.

All other settings can be left as default unless special use cases require otherwise.

User provisioning is the next step. In this case, groups prefixed with cognito_ will be generated(e.g. cognito_developers, cognito_infrastructure) and users will be assigned to these groups.

User pool federated identity

Once the SAML application is created, a federated identity should be provisioned for the Cognito user pool. This can be done by adding a SAML identity provider, under the Federation section.

The metadata file generated by the SAML application needs to be passed to the SAML federated identity. Alternatively, a URL to the metadata file can be added, which allows Cognito to refresh the data automatically when changes are made to the IdP.

Next, attributes mapping will be configured. These are directly correlated to the Okta attribute statements and group attribute statements. In short, SAML attributes should be mapped to user pool attributes. For example, SAML attribute http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress will map to email user pool attribute, while “roles” SAML attribute will map to profile user pool attribute.

Using Terraform, the above can be configured as follow:

# SAML identity provider
resource "aws_cognito_identity_provider" "okta_identity_provider" {
user_pool_id = "${aws_cognito_user_pool.user_pool.id}"
provider_name = "Okta"
provider_type = "SAML"
# URL of the SAML metadata file
provider_details = {
MetadataURL = "${var.okta_metadata_url}"
}
# SAML attribute mapping to user pool attributes
attribute_mapping = {
email = "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"
profile = "roles"
}

}

Once these settings are deployed, Okta can be enabled as an identity provider in the App client settings, under App integration section.

To test the above setup, access Kibana endpoint directly or the service provider initiated flow endpoint, e.g.

https://domainPrefix.auth.region.amazoncognito.com/login?response_type=token&client_id=clientId&redirect_uri=redirectUrl
Expected login page

where:

  • domainPrefix.auth.region.amazoncognito.com — Cognito domain name
  • clientId — user pool client ID
  • redirectUrl — full Kibana endpoint

Note: Cognito SAML federated identity will create a profile for every logged user. These profiles can be accessed under the “Users and groups” section of the Cognito user pool.

Identity pool role-based access provisioning

In a vanilla setup for identity pools, IAM roles will be configured for authenticated and unauthenticated identities. Also, ElastiSearch domain access policy should include permissions for Kibana access via an identity pool. With this setup, all users will have the same level of access.

However, at Condé Nast International, we want to provide different levels of access for cloud platforms and developer teams. For example, an admin will get full privileges for operating ElasticSearch domains, while a developer will require read and write privileges only. This can be achieved by giving users role-based access via IAM roles.

In previous steps, we mapped Cognito user pool profile to the AD groups (aka roles) in Okta. All that we have to do at this stage is to map IAM roles to these AD groups. In the console, this can be achieved as follows:

AD groups mapping to IAM roles

In Terraform the group to IAM role mapping can be configured in the following way:

# role attachement for identity pool
resource "aws_cognito_identity_pool_roles_attachment" "identity_pool_roles" {
identity_pool_id = "${aws_cognito_identity_pool.identity_pool.id}"
role_mapping {
identity_provider = "cognito-idp.${var.region}.amazonaws.com/${aws_cognito_user_pool.user_pool.id}:${var.es_app_client_id}"
ambiguous_role_resolution = "Deny"
type = "Rules"
# role-based access based on AD group
mapping_rule {
claim = "profile"
match_type = "Equals"
role_arn = "${aws_iam_role.cognito_admin_role.arn}"
value = "cognito_infrastructure"
}
mapping_rule {
claim = "profile"
match_type = "Equals"
role_arn = "${aws_iam_role.cognito_rw_role.arn}"
value = "cognito_developer"
}
}# authenticated and unauthenticated roles
roles = {
"authenticated" = "${aws_iam_role.authenticated.arn}"
"unauthenticated" = "${aws_iam_role.unauthenticated.arn}"
}
}

Also, a default or fallback IAM role can be specified if the user is not part of any known AD groups. This can be a Deny role, which will forbid access to Kibana dashboard, or fallback to the default authentication role.

Note: Cognito does not support authentication for a user that is assigned to multiple groups. Hence, it is important to keep 1:1 mapping between a group and a user.

And that’s it! At this point, you should have role-based access to Kibana via Okta and Cognito!

Known Limitations

At the moment, it is not possible to trigger an IdP initiated authentication flow with Cognito. This means that by clicking the Kibana app tile in Okta, the user will not be able to log in. This is a result of Cognito supporting service provider (SP) initiated authentication flow only. Currently, AWS does not have a fix for this issue on the future roadmap.

Bookmark app for Kibana in multiple environments

However, a workaround is possible by creating a bookmark app in Okta, which will simulate an IdP initiated flow. In a nutshell, the bookmark app will call the Kibana endpoint directly, which will redirect the client to Okta for authentication.

Conclusion

Overall, integrating Okta & Cognito for Kibana authentication was a mighty challenge. Multiple components require out of the box configuration and attribute mapping synchronization. However, the result is a solid authentication mechanism for Kibana, with role-based access for multiple teams and a unified process for user provisioning.

--

--

Katie Gamanji
Product and Engineering at Condé Nast

Sailing open-source tooling and supporting the community as an Senior Kubernetes Field Engineer @Apple