diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3a42743 --- /dev/null +++ b/.gitignore @@ -0,0 +1,234 @@ +# Created by https://www.toptal.com/developers/gitignore/api/intellij+all,goland+all,visualstudiocode,vim,macos,linux +# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+all,goland+all,visualstudiocode,vim,macos,linux + +### GoLand+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### GoLand+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + +.idea/* + +!.idea/codeStyles +!.idea/runConfigurations + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff + +# AWS User-specific + +# Generated files + +# Sensitive or high-churn files + +# Gradle + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake + +# Mongo Explorer plugin + +# File-based project format + +# IntelliJ + +# mpeltonen/sbt-idea plugin + +# JIRA plugin + +# Cursive Clojure plugin + +# SonarLint plugin + +# Crashlytics plugin (for Android Studio and IntelliJ) + +# Editor-based Rest Client + +# Android studio 3.1+ serialized cache file + +### Intellij+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + + + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +!*.svg # comment out if you don't need vector files +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim +Sessionx.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +# End of https://www.toptal.com/developers/gitignore/api/intellij+all,goland+all,visualstudiocode,vim,macos,linux diff --git a/README.md b/README.md index 9a4056d..a3284de 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,37 @@ # policy-library + +![GitHub issues](https://img.shields.io/github/issues/abbeylabs/policy-library) +![GitHub](https://img.shields.io/github/license/abbeylabs/policy-library) + Public registry for governing security and access to cloud and data infrastructure + +## Usage + +1. Browse to a module in [library](src/abbey) +2. Copy the module to your project +3. `import` functions or policies you want to use + ``` + import data.abbey.functions + + allow[msg] { + functions.expire_at("1m") + msg := "revoke access after 1 minute" + } + ``` + +## Testing + +```shell +opa test . -v +``` + +## Contributing + +Development happens in the [GitHub repo](https://github.com/abbeylabs/policy-library): + +- [Releases](https://github.com/abbeylabs/policy-library/releases) +- [Issues](https://github.com/abbeylabs/policy-library/issues) + +## License + +This project is licensed under the Apache 2.0 license. See [LICENSE](LICENSE) for more details. diff --git a/src/.manifest b/src/.manifest new file mode 100644 index 0000000..f201267 --- /dev/null +++ b/src/.manifest @@ -0,0 +1,12 @@ +{ + "roots": [ + "abbey", + "soc2" + ], + "metadata": { + "required_builtins": { + "builtin1": [ + ] + } + } +} diff --git a/src/abbey/functions/expire_after.rego b/src/abbey/functions/expire_after.rego new file mode 100644 index 0000000..76b32bf --- /dev/null +++ b/src/abbey/functions/expire_after.rego @@ -0,0 +1,16 @@ +package abbey.functions + +import future.keywords.if + +# Function that checks if the time at `ts` has expired, relative to the time at `approved_at`. +# The `ts` input is a string that can be parsed by Rego's native `time.parse_duration_ns` function. +# Valid string values are derived from https://pkg.go.dev/time#ParseDuration. +# Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". +# This function compares against data under the `system.abbey.target` namespace. +expire_after(ts) := live if { + expires_after := time.parse_duration_ns(ts) + approved_at := time.parse_rfc3339_ns(data.system.abbey.target.grant.approved_at) + expires_at := approved_at + expires_after + now := time.now_ns() + live := (now - expires_at) < 0 +} \ No newline at end of file diff --git a/src/abbey/functions/expire_after_test.rego b/src/abbey/functions/expire_after_test.rego new file mode 100644 index 0000000..f058d9f --- /dev/null +++ b/src/abbey/functions/expire_after_test.rego @@ -0,0 +1,18 @@ +package abbey.functions + +import future.keywords.if + +test_expired if { + not expire_after("1m") with data.system.abbey.target.grant.approved_at as "2023-01-01T01:00:00Z" + with time.now_ns as 1672534900000000000 +} + +test_expired if { + not expire_after("1m") with data.system.abbey.target.grant.approved_at as "2023-01-01T01:00:00Z" + with time.now_ns as 1672534860000000000 +} + +test_not_expired if { + expire_after("1m") with data.system.abbey.target.grant.approved_at as "2023-01-01T01:00:00Z" + with time.now_ns as 0 +} diff --git a/src/abbey/functions/expire_at.rego b/src/abbey/functions/expire_at.rego new file mode 100644 index 0000000..ad7f6fd --- /dev/null +++ b/src/abbey/functions/expire_at.rego @@ -0,0 +1,12 @@ +package abbey.functions + +import future.keywords.if + +# Function that checks if the time at `ts` has expired, relative to the time at `approved_at`. +# The `ts` input is a string representing the RFC 3339 date time format. +# This function compares against data under the `system.abbey.target` namespace. +expire_at(ts) := live if { + expires_at := time.parse_rfc3339_ns(ts) + now := time.now_ns() + live := (now - expires_at) < 0 +} diff --git a/src/abbey/functions/expire_at_test.rego b/src/abbey/functions/expire_at_test.rego new file mode 100644 index 0000000..a741d17 --- /dev/null +++ b/src/abbey/functions/expire_at_test.rego @@ -0,0 +1,18 @@ +package abbey.functions + +import future.keywords.if + +test_expired if { + not expire_at("2023-01-01T02:00:00Z") with data.system.abbey.target.grant.approved_at as "2023-01-01T01:00:00Z" + with time.now_ns as 1672538500000000000 +} + +test_expired if { + not expire_at("2023-01-01T01:00:00Z") with data.system.abbey.target.grant.approved_at as "2023-01-01T01:00:00Z" + with time.now_ns as 1672538400000000000 +} + +test_not_expired if { + expire_at("2023-01-01T01:00:00Z") with data.system.abbey.target.grant.approved_at as "2023-01-01T01:00:00Z" + with time.now_ns as 0 +} \ No newline at end of file diff --git a/src/abbey/soc2/security/dcf_10/system_access_control.rego b/src/abbey/soc2/security/dcf_10/system_access_control.rego new file mode 100644 index 0000000..0b66de8 --- /dev/null +++ b/src/abbey/soc2/security/dcf_10/system_access_control.rego @@ -0,0 +1,11 @@ +# Requires annual access control reviews to be conducted and +# access request forms be filled out for new hires and employee transfers. +# +# Does the organization enforce controls related to the granting or revoking +# of access to sensitive systems and/or applications? +# +# 1. New hire checklist includes access request form +# 2. Employee role changes require new access request form +# +# Covers CC4.1, CC6.2, CC6.3. +package abbey.soc2.security.dcf_10 \ No newline at end of file diff --git a/src/abbey/soc2/security/dcf_2/least_privilege.rego b/src/abbey/soc2/security/dcf_2/least_privilege.rego new file mode 100644 index 0000000..1c7c915 --- /dev/null +++ b/src/abbey/soc2/security/dcf_2/least_privilege.rego @@ -0,0 +1,11 @@ +# Authorizes access to information resources, including data and the systems that +# store or process sensitive data, based on the principle of least privilege. +# +# Does the organization utilize the concept of least privilege, +# allowing only authorized access to processes necessary to accomplish assigned tasks +# in accordance with organizational business functions? +# +# Authorize access to information resources based on least-privilege policy. +# +# Covers CC2.1, CC5.2. +package abbey.soc2.security.dcf_2 \ No newline at end of file diff --git a/src/abbey/soc2/security/dcf_59/role_based_security.rego b/src/abbey/soc2/security/dcf_59/role_based_security.rego new file mode 100644 index 0000000..6fdc2d3 --- /dev/null +++ b/src/abbey/soc2/security/dcf_59/role_based_security.rego @@ -0,0 +1,6 @@ +# Role-based security is in place for internal and external users, including super admin users. +# +# Does the organization enforce a Role-Based Access Control (RBAC) policy over users and resources? +# +# Covers CC1.1, CC6.1, CC6.3, PI1.4. +package abbey.soc2.security.dcf_59