Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
bc52695
fix: secret id overlap with secret key for large secret ids numbers
teyim Jun 19, 2025
8a20c29
fix: secret key header width
teyim Jun 19, 2025
7beb375
chore: bump version to v2.47.0
nimish-ks Jun 20, 2025
44e150a
feat: add custom hook for secret search functionality
nimish-ks Jun 12, 2025
b911819
feat: add GraphQL query to retrieve organization secret keys
nimish-ks Jun 12, 2025
27211f7
feat: integrate secret search functionality into CommandPalette
nimish-ks Jun 12, 2025
1654991
feat: add all_secrets field to EnvironmentType with access control
nimish-ks Jun 12, 2025
ac154e2
feat: add allSecrets field to EnvironmentType
nimish-ks Jun 12, 2025
0eaf75d
feat: add GetOrgSecretKeys query and update Mutation types
nimish-ks Jun 12, 2025
b1a9062
fix: rename secrets field to allSecrets in GetOrgSecretKeys query
nimish-ks Jun 12, 2025
24971c4
feat: add GetOrgSecretKeys query to GraphQL documents
nimish-ks Jun 12, 2025
866d28e
refactor: normalize search query and update secret iteration to use a…
nimish-ks Jun 12, 2025
0861e1c
fix: path construction and added secret path in the dropdown
nimish-ks Jun 12, 2025
ce1ac92
fix: use standard secrets resolver
rohan-chaturvedi Jun 20, 2025
b0eac59
feat: use monospace font for secret keys
rohan-chaturvedi Jun 20, 2025
478974a
fix: add path arg to app secrets query and hook
rohan-chaturvedi Jun 20, 2025
f704e4f
feat: highlight matches
rohan-chaturvedi Jun 20, 2025
a86056e
fix: tweak secret row highlight color on dark theme
rohan-chaturvedi Jun 20, 2025
a59a8d7
fix: correctly set component state when preselecting account (#591)
rohan-chaturvedi Jun 19, 2025
2a75666
feat: update graphql type for appMemberships field
rohan-chaturvedi Jun 19, 2025
0802fae
feat: add org member detail query, remove redundant fields from memb…
rohan-chaturvedi Jun 19, 2025
a471130
chore: regenerate types
rohan-chaturvedi Jun 19, 2025
04a2032
feat: trigger add app member dialog from account id search param
rohan-chaturvedi Jun 19, 2025
339b3de
fix: filter apps in add app menu, misc other fixes
rohan-chaturvedi Jun 19, 2025
c3e783b
feat: trigger manage env scope dialogs from account pages
rohan-chaturvedi Jun 19, 2025
843bea1
fix: add empty state for service account add app menu
rohan-chaturvedi Jun 19, 2025
db018b9
chore: regenerate schema and types
rohan-chaturvedi Jun 20, 2025
3e33e6f
chore: update README and demo (#596)
nimish-ks Jun 24, 2025
2147d48
Update README.md
nimish-ks Jun 24, 2025
813752e
fix: remove ad-hoc styles on delete service account button (#597)
rohan-chaturvedi Jun 27, 2025
dee4739
feat: improve error page (#595)
rohan-chaturvedi Jun 27, 2025
ea6e459
fix: correct spelling of "received" in Lockbox page (#598)
nimish-ks Jun 27, 2025
c3e0f28
style: modify secret key column
teyim Jul 2, 2025
a7c452c
style: modify table column aligmnent
teyim Jul 3, 2025
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
81 changes: 39 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,38 @@
<img height="120" width="450" src="img/phase-lattice-logo.svg" alt="Phase">
</a>

<a href="https://phase.dev">Website</a> |
<a href="https://docs.phase.dev">Documentation</a> |
<a href="https://docs.phase.dev/security">Security</a> |
<a href="https://github.com/phasehq/console/blob/main/CONTRIBUTING.md">Contributing</a> |
<a href="https://slack.phase.dev">Join Slack</a>
<h5>Repos</h5>
<p>
<a href="https://github.com/phasehq/docs">Docs</a> |
<a href="https://github.com/phasehq/cli">CLI</a> |
<a href="https://github.com/phasehq/node-sdk">Node SDK</a> |
<a href="https://github.com/phasehq/python-sdk">Python SDK</a>
<br/>
<a href="https://github.com/phasehq/golang-sdk">Golang SDK</a> |
<a href="https://github.com/phasehq/kubernetes-secrets-operator/tree/main/phase-console">Helm Chart</a> |
<a href="https://github.com/phasehq/kubernetes-secrets-operator">Kubernetes Operator</a> |
<a href="https://github.com/phasehq/terraform-provider-phase">Terraform Provider</a>
</p>
</div>

---

Open source platform for fast-moving engineering teams to secure and deploy application secrets β€” from development to production.

A developer-friendly alternative to **HashiCorp Vault** and **AWS Secrets Manager** that works with your whole team πŸ§‘β€πŸ’».

#### Open source platform for fast-moving engineering teams to secure and deploy application secrets β€” from development to production.
---

# Phase Console
https://github.com/user-attachments/assets/160c721d-a941-440a-bc42-afd419c1df18

[Phase Console Demo](https://github.com/user-attachments/assets/cd6b1ffe-6cb4-4a2b-8ae1-9daa61ed3a5a)

| | **Features** |
| --- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| πŸ“ˆ | **[Phase Console](https://console.phase.dev)**: Dashboard for seamlessly creating, managing, rotating secrets, and environment variables |
| ⌨️ | **[CLI](https://github.com/phasehq/cli)**: Import existing secrets from `.env` files, encrypt them, and securely inject them in your application at runtime |
| 🀫 | **[Secret management](https://docs.phase.dev/console/apps)**: Secret Diffs, version control, and recovery |
| πŸ™‹ | **[RBAC](https://docs.phase.dev/console/users#user-roles)**: Fine-grained, role-based, and cryptographic access control, per application, per environment. |
| πŸ”Œ | **[Integrations](https://docs.phase.dev/#integrate-phase)**: Automatically sync secrets to GitHub, Cloudflare Pages, GitLab CI, Railway, AWS Secrets Manager, etc. |
| ![Kubernetes](img/kubernetes.svg) | **[Kubernetes](https://docs.phase.dev/integrations/platforms/kubernetes)**: Automatically deploy secrets to your Kubernetes Cluster with End-to-End encryption via Phase Secrets Operator |
| ⛓️ | **[Secret referencing & overrides](https://docs.phase.dev/console/secrets)**: Create personal secrets. Inherit values from other secrets |
| 🌐 | **[REST API](https://docs.phase.dev/public-api/secrets#get-secrets)**: Access and manage secrets programmatically |
| ⌨️ | **[CLI](https://github.com/phasehq/cli)**: Import existing secrets from `.env` files, and securely inject them in your application at runtime or create virtual shells with secrets |
| 🀫 | **[Secret management](https://docs.phase.dev/console/apps)**: Manage secrets across environments, view secret diffs, track version history, and restore secret values with a single click |
| πŸ™‹ | **[Role-based Access Control](https://docs.phase.dev/console/users#user-roles)**: Fine-grained, role-based, and cryptographic access control, per application, per environment. |
| πŸ” | **[Secret sync](https://docs.phase.dev/#integrate-phase)**: Automatically sync secrets to GitHub, Cloudflare Pages, Vercel, GitLab CI, Railway, AWS Secrets Manager, etc. |
| ![Kubernetes](img/kubernetes.svg) | **[Kubernetes](https://docs.phase.dev/integrations/platforms/kubernetes)**: Automatically sync secrets to your Kubernetes Cluster and reload deployments via the Phase Secrets Operator |
| ![Terraform Provider](img/terraform.svg) | **[Terraform](https://docs.phase.dev/integrations/platforms/hashicorp-terraform)**: Manage secrets in your HashiCorp Terraform Iac workflows. |
| ⛓️ | **[Secret referencing & overrides](https://docs.phase.dev/console/secrets)**: Create personal secrets without affecting others on the team. Reference secret values across apps and environments |
| 🌐 | **[REST API](https://docs.phase.dev/public-api/secrets#get-secrets)**: Access and manage secrets programmatically with any http client |
| πŸ“¦ | **[SDKs](https://docs.phase.dev/sdks)**: SDKs for integrating Phase with various programming languages and frameworks
| πŸ₯‘ | **[Self Hosting](https://docs.phase.dev)**: Run Phase on your own infrastructure |
| πŸ” | **[Audit Logs]()**: Complete visibility into every change and access event | | |
Expand All @@ -41,42 +44,33 @@ https://github.com/user-attachments/assets/160c721d-a941-440a-bc42-afd419c1df18

---

## CLI - Import, Encrypt and Inject secrets

![Phase CI](img/phase-cli-import-run.webp)
## CLI

```fish
Ξ» phase
Ξ» phase --help
Securely manage application secrets and environment variables with Phase.

@@@
@@@@@@@@@@
@@@@@@@@@@@@@@@@
P@@@@@&@@@?&@@&@@@@@P
P@@@@# @&@ @P@@@
&@@@# *@& #@@@&
&@@@5 &@? 5@@@&
Y@@@# ^@@ #@@@J
#@@@7 B@5 7@@@#
#@@@? .@@. ?@@@#
@@@@& 5@G &@@@7
#@@@B @@^ #@@@B
B@@@@ .@# 7@@@@B
@@@@@@ &.@ P@@@@@7
@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@
@@@@@@@@
@@@
/$$
| $$
/$$$$$$ | $$$$$$$ /$$$$$$ /$$$$$$$ /$$$$$$
/$$__ $$| $$__ $$ |____ $$ /$$_____/ /$$__ $$
| $$ \ $$| $$ \ $$ /$$$$$$$| $$$$$$ | $$$$$$$$
| $$ | $$| $$ | $$ /$$__ $$ \____ $$| $$_____/
| $$$$$$$/| $$ | $$| $$$$$$$ /$$$$$$$/| $$$$$$$
| $$____/ |__/ |__/ \_______/|_______/ \_______/
| $$
|__/

options:
-h, --help show this help message and exit
--version, -v
show program's version number and exit

Commands:

auth πŸ’» Authenticate with Phase
init πŸ”— Link your project with your Phase app
run πŸš€ Run and inject secrets to your app
shell 🐚 Launch a sub-shell with secrets as environment variables (BETA)
secrets πŸ—οΈ Manage your secrets
secrets list πŸ“‡ List all the secrets
secrets get πŸ” Get a specific secret by key
Expand All @@ -87,6 +81,7 @@ Commands:
secrets export πŸ₯‘ Export secrets in a dotenv format
users πŸ‘₯ Manage users and accounts
users whoami πŸ™‹ See details of the current user
users switch πŸͺ„ Switch between Phase users, orgs and hosts
users logout πŸƒ Logout from phase-cli
users keyring πŸ” Display information about the Phase keyring
docs πŸ“– Open the Phase CLI Docs in your browser
Expand All @@ -111,7 +106,9 @@ The quickest and most reliable way to get started is by signing up on the [Phase
| | **Deploy Phase Console on your infrastructure** |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
|![Docker](img/docker.svg) | [Docker Compose](https://docs.phase.dev/self-hosting/docker-compose) |
|![Kubernetes](img/kubernetes.svg) | [Kubernetes (Helm chart)](https://docs.phase.dev/self-hosting/kubernetes) |
|![AWS](img/aws.svg) | [AWS](https://docs.phase.dev/self-hosting/aws) |
|![AWS EKS](img/aws-eks.svg) | [AWS EKS (Helm chart)](https://docs.phase.dev/self-hosting/aws-eks) |
|![GCP](img/gcp.svg) | [Google Cloud Platform](https://docs.phase.dev/self-hosting/gcp) |
|![Azure](img/azure.svg) | [Azure](https://docs.phase.dev/self-hosting/azure) |
|![DigitalOcean](img/do.svg) | [DigitalOcean](https://docs.phase.dev/self-hosting/digitalocean) |
Expand Down
30 changes: 25 additions & 5 deletions backend/backend/graphene/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ class OrganisationMemberType(DjangoObjectType):
role = graphene.Field(RoleType)
self = graphene.Boolean()
last_login = graphene.DateTime()
app_memberships = graphene.List(graphene.NonNull(lambda: AppType))
app_memberships = graphene.List(graphene.NonNull(lambda: AppMembershipType))
tokens = graphene.List(graphene.NonNull(lambda: UserTokenType))
network_policies = graphene.List(graphene.NonNull(lambda: NetworkAccessPolicyType))

Expand Down Expand Up @@ -497,7 +497,10 @@ def resolve_override(self, info):

class EnvironmentType(DjangoObjectType):
folders = graphene.NonNull(graphene.List(SecretFolderType))
secrets = graphene.NonNull(graphene.List(SecretType))
secrets = graphene.NonNull(
graphene.List(SecretType),
path=graphene.String(required=False)
)
folder_count = graphene.Int()
secret_count = graphene.Int()
members = graphene.NonNull(graphene.List(OrganisationMemberType))
Expand All @@ -520,7 +523,7 @@ class Meta:
"updated_at",
)

def resolve_secrets(self, info, path="/"):
def resolve_secrets(self, info, path=None):

org = self.app.organisation
if not user_has_permission(
Expand All @@ -535,11 +538,12 @@ def resolve_secrets(self, info, path="/"):

filter = {"environment": self, "deleted_at": None}

if path:
if path is not None:
filter["path"] = path

return Secret.objects.filter(**filter).order_by("-created_at")


def resolve_folders(self, info, path=None):
if not user_can_access_environment(info.context.user.userId, self.id):
raise GraphQLError("You don't have access to this environment")
Expand Down Expand Up @@ -655,13 +659,29 @@ def resolve_updated_at(self, info):
def resolve_members(self, info):
return self.members.filter(deleted_at=None)

class AppMembershipType(DjangoObjectType):
environments = graphene.NonNull(graphene.List(EnvironmentType))

class Meta:
model = App
fields = (
"id",
"name",
"sse_enabled",
)

def resolve_environments(self, info):
# Only return filtered environments if set
return getattr(self, "filtered_environments", [])



class ServiceAccountType(DjangoObjectType):

third_party_auth_enabled = graphene.Boolean()
handlers = graphene.List(ServiceAccountHandlerType)
tokens = graphene.List(ServiceAccountTokenType)
app_memberships = graphene.List(graphene.NonNull(AppType))
app_memberships = graphene.List(graphene.NonNull(AppMembershipType))
network_policies = graphene.List(graphene.NonNull(lambda: NetworkAccessPolicyType))

class Meta:
Expand Down
11 changes: 7 additions & 4 deletions backend/backend/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ class Query(graphene.ObjectType):
organisation_members = graphene.List(
OrganisationMemberType,
organisation_id=graphene.ID(),
user_id=graphene.ID(),
role=graphene.List(graphene.String),
member_id=graphene.ID(required=False),
role=graphene.List(graphene.String, required=False),
)
organisation_global_access_users = graphene.List(
OrganisationMemberType, organisation_id=graphene.ID()
Expand Down Expand Up @@ -440,13 +440,16 @@ def resolve_organisation_name_available(root, info, name):
resolve_license = resolve_license
resolve_organisation_license = resolve_organisation_license

def resolve_organisation_members(root, info, organisation_id, role, user_id=None):
def resolve_organisation_members(root, info, organisation_id, role = None, member_id=None):
if not user_is_org_member(info.context.user.userId, organisation_id):
raise GraphQLError("You don't have access to this organisation")

filter = {"organisation_id": organisation_id, "deleted_at": None}

if role:
if member_id is not None:
filter["id"] = member_id

if role is not None:
roles = [user_role.lower() for user_role in role]
filter["roles__in"] = roles

Expand Down
2 changes: 1 addition & 1 deletion backend/version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.46.0
v2.47.0
Loading
Loading