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

Add SM2A RBAC to SM2A #272

Open
wants to merge 3 commits into
base: dev
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
1 change: 0 additions & 1 deletion .github/actions/terraform-deploy-sm2a/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,3 @@ runs:
run: |
cd ./infrastructure
terraform output -json Airflow_url > ${HOME}/output_sm2a_workflows_endpoint.json

17 changes: 17 additions & 0 deletions sm2a/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,3 +178,20 @@ The retrieved secrets are then stored in a .env file.
The [python-dotenv](https://pypi.org/project/python-dotenv/) library is used to access the variables stored in the .env file.
These variables can now be used within your DAG tasks.

## DAG Launcher Role Overview
The DAG Launcher role in Airflow is designed to provide users with the necessary permissions to manage and launch DAGs
in the Airflow UI. This role allows users to perform actions such as reading DAG runs,
and interacting with various views like Task Instances, Jobs, and XComs.

The permissions granted are tailored to streamline the interaction with the DAG management interface,
enabling effective monitoring and control over DAG executions.

### Key Permissions Assigned to the DAG Launcher Role:
- Permission on Dag runs for `veda_discover`, `veda_dataset_pipeline`, `veda_collection_pipeline`
- Read access to "My Profile", "DAG Runs", "Jobs", "Task Instances", "XComs", "DAG Dependencies", "Task Logs", and "Website".
- Create, Read, Edit, and Menu Access for DAG runs and DAG-related views (e.g., DAGs, Documentation).
- Edit access to specific DAGs like veda_discover.
- Integrating GitHub Users with the Airflow DAG UI
To grant users access to the Airflow UI, including the ability to manage DAGs and view the Swagger interface,
GitHub users must be added to a GitHub [team](https://github.com/orgs/NASA-IMPACT/teams/veda-dag-launcher).

5 changes: 4 additions & 1 deletion sm2a/airflow_services/webserver_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
AUTH_ROLES_MAPPING = {
"Viewer": ["Viewer"],
"Admin": ["Admin"],
"Dag_Launcher": ["DAG Launcher"],
}
# If you wish, you can add multiple OAuth providers.
OAUTH_PROVIDERS = [
Expand All @@ -102,9 +103,11 @@

FAB_ADMIN_ROLE = "Admin"
FAB_VIEWER_ROLE = "Viewer"
FAB_DAG_LAUNCHER_ROLE = "Dag_Launcher"
FAB_PUBLIC_ROLE = "Public" # The "Public" role is given no permissions
TEAM_ID_A_FROM_GITHUB = os.getenv("GH_ADMIN_TEAM_ID")
TEAM_ID_B_FROM_GITHUB = os.getenv("GH_USER_TEAM_ID")
TEAM_ID_DAG_LAUNCHER_FROM_GITHUB = os.getenv("GH_DAG_LAUNCHER_TEAM_ID")


def team_parser(team_payload: dict[str, Any]) -> list[int]:
Expand All @@ -119,6 +122,7 @@ def map_roles(team_list: list[int]) -> list[str]:
team_role_map = {
TEAM_ID_A_FROM_GITHUB: FAB_ADMIN_ROLE,
TEAM_ID_B_FROM_GITHUB: FAB_VIEWER_ROLE,
TEAM_ID_DAG_LAUNCHER_FROM_GITHUB: FAB_DAG_LAUNCHER_ROLE,
}
return list(set(team_role_map.get(team, FAB_PUBLIC_ROLE) for team in team_list))

Expand All @@ -141,7 +145,6 @@ def get_oauth_user_info(
team_data = remote_app.get("user/teams")
teams = team_parser(team_data.json())
roles = map_roles(teams)
log.debug(f"User info from Github: {user_data}\nTeam info from Github: {teams}")
print(f"User info from Github: {user_data}\nTeam info from Github: {teams}")
return {"username": "github_" + user_data.get("login"), "role_keys": roles}

Expand Down
4 changes: 2 additions & 2 deletions sm2a/infrastructure/locals.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
provider "aws" {
alias = "aws_current"
region = var.aws_region
alias = "aws_current"
region = var.aws_region
}

data "aws_caller_identity" "current" {}
Expand Down
6 changes: 5 additions & 1 deletion sm2a/infrastructure/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ module "sma-base" {
{
name = "GH_USER_TEAM_ID"
value = var.gh_user_team_id
},
{
name = "GH_DAG_LAUNCHER_TEAM_ID"
value = var.gh_dag_launcher_team_id
}


Expand All @@ -89,7 +93,7 @@ module "sma-base" {
STAC_INGESTOR_API_URL = var.stac_ingestor_api_url
STAC_URL = var.stac_url
VECTOR_SECRET_NAME = var.vector_secret_name
ASSUME_ROLE_READ_ARN = var.assume_role_read_arn
ASSUME_ROLE_READ_ARN = var.assume_role_read_arn
ASSUME_ROLE_WRITE_ARN = var.assume_role_write_arn
}
}
Expand Down
2 changes: 1 addition & 1 deletion sm2a/infrastructure/s3_event_bridge_lambda.tf
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ resource "aws_lambda_permission" "s3_invoke" {


resource "aws_s3_bucket_notification" "bucket_notification" {
count = var.eis_storage_bucket_name != "null" ? 1 : 0
count = var.eis_storage_bucket_name != "null" ? 1 : 0
bucket = var.eis_storage_bucket_name

lambda_function {
Expand Down
17 changes: 10 additions & 7 deletions sm2a/infrastructure/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -122,26 +122,26 @@ variable "stac_url" {
}

variable "vector_secret_name" {
type = string
type = string
default = "null"
}

variable "eis_storage_bucket_name" {
type = string
type = string
default = "null"
}

variable "eis_s3_invoke_filter_prefix" {
type = string
type = string
default = "null"
}
variable "sm2a_secret_manager_name" {
type = string
type = string
default = "null"
}

variable "target_dag_id" {
type = string
type = string
default = "null"
}

Expand Down Expand Up @@ -174,11 +174,14 @@ variable "workers_task_retries" {
}

variable "assume_role_read_arn" {
type = string
type = string
default = ""
}

variable "assume_role_write_arn" {
type = string
type = string
default = ""
}
variable "gh_dag_launcher_team_id" {
default = "VEDA-DAG-Launcher"
}
57 changes: 57 additions & 0 deletions sm2a/scripts/create_sm2a_role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from airflow.www.app import create_app


def create_dag_launcher_role():
app = create_app()
with app.app_context():
security_manager = app.appbuilder.sm
role_name = "DAG Launcher"

# Define permissions
permissions = [
("can_read", "My Profile"),
("can_create", "DAG Runs"),
("can_read", "DAG Runs"),
("can_edit", "DAG Runs"),
("menu_access", "DAG Runs"),
("menu_access", "Browse"),
("can_read", "Jobs"),
("menu_access", "Jobs"),
("can_read", "Task Instances"),
("menu_access", "Task Instances"),
("can_read", "XComs"),
("menu_access", "DAGs"),
("menu_access", "Documentation"),
("menu_access", "Docs"),
("can_read", "DAG Dependencies"),
("can_read", "Task Logs"),
("can_read", "Website"),
("can_edit", "DAG:veda_discover"),
("can_read", "DAG:veda_discover"),
("can_edit", "DAG:veda_dataset_pipeline"),
("can_read", "DAG:veda_dataset_pipeline"),
("can_edit", "DAG:veda_collection_pipeline"),
("can_read", "DAG:veda_collection_pipeline")
]

# Check if the role exists, create it if not
role = security_manager.find_role(role_name)
if not role:
role = security_manager.add_role(role_name)

# Assign permissions to the role
for perm_name, view_menu_name in permissions:
# Ensure the menu exists
security_manager.add_permissions_menu(view_menu_name)

# Ensure permission exists
permission = security_manager.get_permission(perm_name, view_menu_name)
if permission and permission not in role.permissions:
security_manager.add_permission_to_role(role, permission)

print(f"Role '{role_name}' created with specified permissions.")


# Execute the script
if __name__ == "__main__":
create_dag_launcher_role()
Loading