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

S175 initial version #1

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
> Description here

### Fixes
> paste links to issues/tasks in project management
- []()

### Features
> paste links to issues/tasks in project management
- []()

### Change implications

- dependencies added/changed? **yes (explain) / no**
28 changes: 28 additions & 0 deletions .github/workflows/terraform_lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Terraform CI - Lint

on:
[push]

jobs:
tf_lint:
name: 'Terraform lint (on tf ${{ matrix.terraform_version }})'
runs-on: ubuntu-latest
strategy:
matrix:
terraform_version: [ '~1.5.0', '~1.6.0', '~1.7.0', 'latest'] # in theory, we go down to 1.3, but I think that's overkill for lint
Copy link
Member

Choose a reason for hiding this comment

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

permissions:
contents: 'read'
id-token: 'write'
steps:
- name: Check out code
uses: actions/checkout@v4

- name: 'setup Terraform'
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ matrix.terraform_version }}

- name: 'lint Terraform code'
# see https://www.terraform.io/cli/commands/fmt
run:
terraform fmt -check -recursive -diff .
42 changes: 42 additions & 0 deletions .github/workflows/terraform_validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: Terraform CI - validate

on:
[push]

jobs:
tf_validate:
name: 'Terraform validate (on tf ${{ matrix.terraform_version }})'
runs-on: ubuntu-latest
strategy:
matrix:
terraform_version: ['~1.3.0', '~1.4.0', '~1.5.0', '~1.6.0', '~1.7.0', 'latest']
permissions:
contents: 'read'
id-token: 'write'

steps:
- name: Check out code
uses: actions/checkout@v4

- name: 'setup Terraform'
uses: hashicorp/setup-terraform@v3
with:
terraform_version: ${{ matrix.terraform_version }}

- name: 'Terraform - validate examples/create_psoxy_connections'
davidfq marked this conversation as resolved.
Show resolved Hide resolved
working-directory: examples/create_psoxy_connections
run: |
terraform init
terraform validate

- name: 'Terraform - validate modules/cognito_tenant_api_auth'
working-directory: modules/cognito_tenant_api_auth
run: |
terraform init
terraform validate

- name: 'Terraform - validate modules/psoxy_connection'
working-directory: modules/psoxy_connection
run: |
terraform init
terraform validate
29 changes: 29 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Local .terraform directories
**/.terraform/*

# .tfstate files
**/*.tfstate
**/*.tfstate.*

# Crash log files
crash.log

# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Include override files you do wish to add to version control using negated pattern
#
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*
21 changes: 19 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,19 @@
# terraform-aws-worklytics
Terraform module for AWS resources to support Worklytics Data Exports, and Tenant API access.
# Terraform AWS Worklytics

A collection of Terraform submodules to support the Worklytics Tenant API using Amazon Web Services (AWS) resources.

- [Tenant API: authentication via AWS Cognito](modules/cognito_tenant_api_auth)
- [Tenant API: create a Psoxy Connection](modules/psoxy_connection)

The main use-case for these submodules is to create [Psoxy Connections] in Worklytics via its [Tenant API].

After a successful Psoxy deployment (Data Source fully configured, Psoxy instance tested and running), the last step
should be to create the actual connection in the [Data Sources] section of the Worklytics Web App. These submodules
provide a way to automate this process.
Comment on lines +11 to +12
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
should be to create the actual connection in the [Data Sources] section of the Worklytics Web App. These submodules
provide a way to automate this process.
should be to create the actual connection in the [Data Sources] section of the Worklytics Web App, either manually following the instructions in the TO-DO files, or automatically with a script that is produced by these sub-modules.

not totally sold on this... what do you think?


See the [examples/create_psoxy_connections] for a complete usage example.

[Psoxy Connections]: https://docs.worklytics.co/psoxy
[Tenant API]: https://docs.worklytics.co/knowledge-base/tenant-api
[Data Sources]: https://app.worklytics.co/analytics/data-sources
[examples/create_psoxy_connections]: examples/create_psoxy_connections
8 changes: 8 additions & 0 deletions examples/create_psoxy_connections/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

# ignore variable files for examples; assume people are testing in dev or something
**/terraform.tfvars

# ignore .terraform state/lock files; again, presume people are playing with examples in dev or something
**/.terraform
**/.terraform.lock.hcl
**/TODO**
29 changes: 29 additions & 0 deletions examples/create_psoxy_connections/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Create Psoxy Connections Example

This example illustrates how to create Psoxy connections in Worklytics via its Tenant API.

Assuming you've set up a Psoxy instance in AWS, the example will create an AWS Cognito Identity Pool to authenticate
with the Tenant API, and a shell script that creates a Psoxy Connection for each one of the Data Sources configured in
your Psoxy instance.

Terraform variables used:

```hcl
worklytics_tenant_id = "116863361842113328137"
user_principal_email = "[email protected]"
psoxy_connections = [{
integration = "data-source-psoxy",
kind = "aws",
endpoint = "https://acme.execute-api.us-east-1.amazonaws.com/data-source-psoxy/",
region = "us-east-1",
role_arn = "psoxy::caller::arn"
}]
```

- `worklytics_tenant_id` is the unique ID of your Worklytics tenant (obtain from Worklytics Web App).
- `user_principal_email` is the email of the user principal that will be used to authenticate with the Tenant API,
and must be registered as `DataConnectionAdmin` via the Worklytics Web App.
- `psoxy_connections` is a collection of the attributes for each Data Source configured in your Psoxy instance.

**Once the Terraform script is executed, and the shell script is created, make sure that the user principal email is
registered as `DataConnectionAdmin` in the Worklytics Web App.**
37 changes: 37 additions & 0 deletions examples/create_psoxy_connections/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# create the resources needed to auth with the Worklytics Tenant API
module "tenant_api_auth" {
source = "../../modules/cognito_tenant_api_auth"

resource_name_prefix = var.resource_name_prefix
worklytics_tenant_id = var.worklytics_tenant_id
user_principal_email = var.user_principal_email
tenant_api_host = var.tenant_api_host
}

# create script files for each Psoxy connection
module "create_psoxy_connection_script" {
source = "../../modules/psoxy_connection"

identity_pool_id = module.tenant_api_auth.worklytics_identity_pool_id
identity_pool_region = module.tenant_api_auth.worklytics_identity_pool_region
identity_pool_user_principal = module.tenant_api_auth.worklytics_identity_pool_user_principal

for_each = {
for psoxy_connection in var.psoxy_connections :
psoxy_connection.integration => psoxy_connection
}
psoxy_connection = {
integration = each.value.integration
region = each.value.region
role_arn = each.value.role_arn
endpoint = each.value.endpoint
bucket = each.value.bucket
parser_id = each.value.parser_id
github_organization = each.value.github_organization
}
psoxy_connection_script_path = coalesce(var.psoxy_connection_script_path, path.module)
psoxy_connection_script_filename = "create_${each.value.integration}-${index(var.psoxy_connections, each.value) + 1}_connection.sh"

tenant_api_host = var.tenant_api_host
worklytics_tenant_id = var.worklytics_tenant_id
}
7 changes: 7 additions & 0 deletions examples/create_psoxy_connections/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
output "worklytics_tenant_api_identity_pool_user_principal" {
value = module.tenant_api_auth.worklytics_identity_pool_user_principal
}

output "worklytics_tenant_api_scripts" {
value = { for key, value in module.create_psoxy_connection_script : key => value.worklytics_tenant_api_script_file.filename }
}
50 changes: 50 additions & 0 deletions examples/create_psoxy_connections/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
variable "resource_name_prefix" {
type = string
description = "Prefix to give to names of infra created by this module, where applicable."
default = "worklytics-tenant-api-"
}

variable "worklytics_tenant_id" {
type = string
description = "Numeric ID of your Worklytics tenant's service account (obtain from Worklytics Web App)."

validation {
condition = var.worklytics_tenant_id == null || can(regex("^\\d{21}$", var.worklytics_tenant_id))
error_message = "`worklytics_tenant_id` must be a 21-digit numeric value. (or `null`, for pre-production use case where you don't want external entity to be allowed to assume the role)."
}
}

variable "tenant_api_host" {
type = string
description = "Host of the Worklytics Tenant API: the domain by which Cognito will refer users."
default = "intl.worklytics.co"
}

variable "region" {
type = string
description = "The AWS region where Cognito Identity Pool is created."
default = "us-east-1"
}

variable "user_principal_email" {
type = string
description = "The email of the user that has been granted access to the Worklytics Tenant API (configure in Worklytics Web App)."
}

variable "psoxy_connections" {
davidfq marked this conversation as resolved.
Show resolved Hide resolved
type = list(object({
integration = string # The integration ID to use for this connection.
region = string # The AWS region of the Proxy instance.
role_arn = string # The ARN role to invoke the Proxy instance.
endpoint = optional(string) # The endpoint of the lambda function (Work Data connections use-case).
bucket = optional(string) # The S3 bucket (Bulk Data connections use-case).
parser_id = optional(string) # Bulk Data connections only.
github_organization = optional(string) # GitHub Connections only.
}))
description = "The connection details for Psoxy connections to be created via Worklytics Tenant API."
}

variable "psoxy_connection_script_path" {
type = string
description = "Where to create the script to create the Psoxy connection"
}
5 changes: 5 additions & 0 deletions modules/cognito_tenant_api_auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Module AWS Cognito Tenant API Auth

This module creates an AWS Cognito Identity Pool to authenticate with the Worklytics Tenant API.

See the [examples/create_psoxy_connections](../../examples/create_psoxy_connections) for a complete usage example.
38 changes: 38 additions & 0 deletions modules/cognito_tenant_api_auth/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 3.0"
}
}
}

provider "aws" {
region = var.region
}

resource "aws_cognito_identity_pool" "worklytics_identity_pool" {
identity_pool_name = "${var.resource_name_prefix}identity-pool"
allow_unauthenticated_identities = false
allow_classic_flow = false
developer_provider_name = var.tenant_api_host
}

resource "aws_iam_policy" "cognito_developer_identities" {
name = "${aws_cognito_identity_pool.worklytics_identity_pool.identity_pool_name}_CognitoDeveloperIdentityForWorklyticsTerraform"
description = "Allow principal to read and lookup developer identities from Cognito Identity: ${aws_cognito_identity_pool.worklytics_identity_pool.id}"

policy = jsonencode(
{
"Version" : "2012-10-17",
"Statement" : [
{
"Action" : [
"cognito-identity:GetOpenIdTokenForDeveloperIdentity",
],
"Effect" : "Allow",
"Resource" : aws_cognito_identity_pool.worklytics_identity_pool.arn
}
]
})
}
15 changes: 15 additions & 0 deletions modules/cognito_tenant_api_auth/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
output "worklytics_identity_pool_id" {
value = aws_cognito_identity_pool.worklytics_identity_pool.id
}

output "worklytics_identity_pool_arn" {
value = aws_cognito_identity_pool.worklytics_identity_pool.arn
}

output "worklytics_identity_pool_region" {
value = var.region
}

output "worklytics_identity_pool_user_principal" {
value = var.user_principal_email
}
36 changes: 36 additions & 0 deletions modules/cognito_tenant_api_auth/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
variable "resource_name_prefix" {
type = string
description = "Prefix to give to names of infra created by this module, where applicable."
default = "worklytics-tenant-api-"
}

variable "worklytics_tenant_id" {
type = string
description = "Numeric ID of your Worklytics tenant's service account (obtain from Worklytics Web App)."

validation {
condition = var.worklytics_tenant_id == null || can(regex("^\\d{21}$", var.worklytics_tenant_id))
error_message = "`worklytics_tenant_id` must be a 21-digit numeric value. (or `null`, for pre-production use case where you don't want external entity to be allowed to assume the role)."
}
}

# This will appear in the AWS console (Amazon Cognito > Identity Pools > Identity Pool Name) as a "Linked login" in
# identity browser of the pool. In development, don't use `localhost:8080` as this is used as the value for
# `developer_provider_name` pool which is subject to some restrictions: only alphanumeric characters, dots, underscores
# and hyphens
variable "tenant_api_host" {
type = string
description = "Host of the Worklytics Tenant API: the domain by which Cognito will refer users."
default = "intl.worklytics.co"
}

variable "region" {
type = string
description = "The AWS region where Cognito Identity Pool is created."
default = "us-east-1"
}

variable "user_principal_email" {
type = string
description = "The email of the user that has been granted access to the Worklytics Tenant API (configure in Worklytics Web App)."
}
6 changes: 6 additions & 0 deletions modules/psoxy_connection/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Module Psoxy Connection

This module creates a shell script that creates Psoxy Connections via the Worklytics Tenant API. It requires
an [AWS Cognito Identity Pool for authentication](../cognito_tenant_api_auth).

See the [examples/create_psoxy_connections](../../examples/create_psoxy_connections) for a complete usage example.
Loading