mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-02 15:40:03 +08:00
* docs: align page file names and nav labels with published URLs Signed-off-by: Johnny Greco <jogreco@nvidia.com> * docs: redirect moved dev pages and fix agent guide redirects Signed-off-by: Johnny Greco <jogreco@nvidia.com> * ci(docs): check that page URLs match their file paths Signed-off-by: Johnny Greco <jogreco@nvidia.com> * fix(docs): align navigation checks with repo conventions Signed-off-by: Johnny Greco <jogreco@nvidia.com> * docs: omit historical redirect aliases Signed-off-by: Johnny Greco <jogreco@nvidia.com> * fix(docs): preserve published overview and TypeScript URLs Signed-off-by: Johnny Greco <jogreco@nvidia.com> * fix(docs): redirect unversioned overview and TypeScript URLs Signed-off-by: Johnny Greco <jogreco@nvidia.com> --------- Signed-off-by: Johnny Greco <jogreco@nvidia.com>
228 lines
7.6 KiB
Plaintext
228 lines
7.6 KiB
Plaintext
---
|
|
# SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
title: "Grant GitHub Push Access to a Sandboxed Agent"
|
|
sidebar-title: "GitHub Push Access"
|
|
slug: "tutorials/github-push-access"
|
|
description: "Launch an agent with a GitHub provider, diagnose a denied push, and grant repository-scoped write access."
|
|
keywords: "Generative AI, Cybersecurity, Tutorial, GitHub, Sandbox, Policy, Claude Code"
|
|
---
|
|
|
|
This tutorial shows how provider access and sandbox policy work together. You
|
|
attach a GitHub provider that contributes read-only GitHub access, observe a
|
|
denied push, and add a user policy that permits writes to one repository.
|
|
|
|
The built-in [default policy](/how-it-works/policies/default-policy) does not grant network
|
|
access. Imported provider profiles contribute the endpoints and executable
|
|
paths needed by their providers.
|
|
|
|
## Prerequisites
|
|
|
|
You need:
|
|
|
|
- A working OpenShell installation and active gateway.
|
|
- An OCI image you built with Claude Code, `git`, and the GitHub CLI installed.
|
|
- An Anthropic API key.
|
|
- A GitHub fine-grained personal access token with read and write access to the
|
|
target repository's contents.
|
|
- A scratch GitHub repository that you can push to.
|
|
|
|
Use two host terminals. Terminal 1 runs the agent. Terminal 2 inspects denials
|
|
and updates policy.
|
|
|
|
<Steps toc={true}>
|
|
|
|
## Import the Provider Profiles
|
|
|
|
Review the [Claude Code profile](https://github.com/NVIDIA/OpenShell/blob/main/providers/claude-code.yaml)
|
|
and [GitHub profile](https://github.com/NVIDIA/OpenShell/blob/main/providers/github.yaml).
|
|
Confirm that their `binaries` paths match the executables in your image, then
|
|
import them directly. If a path or endpoint grant needs to change, edit a local
|
|
copy and import it with `-f` instead.
|
|
|
|
```shell
|
|
openshell profile import --url https://raw.githubusercontent.com/NVIDIA/OpenShell/main/providers/claude-code.yaml --global
|
|
openshell profile import --url https://raw.githubusercontent.com/NVIDIA/OpenShell/main/providers/github.yaml --global
|
|
```
|
|
|
|
The gateway contains no built-in profiles. Import each profile once per gateway
|
|
at the scope where users need it.
|
|
|
|
## Create the Providers
|
|
|
|
Create provider instances from credentials in your host environment. Passing a
|
|
credential on the same command line exports it only to that command:
|
|
|
|
```shell
|
|
ANTHROPIC_API_KEY=<your-anthropic-key> \
|
|
openshell provider create --name my-claude --type claude-code --from-existing
|
|
|
|
GITHUB_TOKEN=<your-github-token> \
|
|
openshell provider create --name my-github --type github --from-existing
|
|
```
|
|
|
|
OpenShell stores the credentials through the configured credential driver. The
|
|
agent receives opaque placeholders; the sandbox proxy resolves them only for
|
|
endpoints allowed by the corresponding profile.
|
|
|
|
## Start the Agent
|
|
|
|
In terminal 1, start Claude Code from your image and attach both providers:
|
|
|
|
```shell
|
|
openshell sandbox create \
|
|
--name github-demo \
|
|
--from registry.example.com/your-org/claude-agent:latest \
|
|
--provider my-claude \
|
|
--provider my-github \
|
|
-- claude
|
|
```
|
|
|
|
To use an existing sandbox, attach the providers from a host terminal, then
|
|
start a new agent process so it receives the provider environment variables:
|
|
|
|
```shell
|
|
openshell sandbox provider attach <sandbox-name> my-claude
|
|
openshell sandbox provider attach <sandbox-name> my-github
|
|
openshell sandbox connect <sandbox-name>
|
|
```
|
|
|
|
## Attempt a Push
|
|
|
|
Ask the agent to create a file and push it to your scratch repository. Replace
|
|
`<org>` and `<repo>` with the repository owner and name:
|
|
|
|
```md title="Prompt" wordWrap showLineNumbers={false}
|
|
Create `hello_world.py`, commit it, and push it to
|
|
`https://github.com/<org>/<repo>.git`. Use the GitHub credentials already
|
|
available in the environment. Do not ask me to paste a token.
|
|
```
|
|
|
|
The push fails. The GitHub profile permits clone and fetch operations but does
|
|
not permit `git-receive-pack`, the Git Smart HTTP operation used for a push.
|
|
The credential remains attached and endpoint-scoped; changing the token would
|
|
not grant the missing network authority.
|
|
|
|
## Inspect the Denial
|
|
|
|
In terminal 2, inspect recent sandbox logs:
|
|
|
|
```shell
|
|
openshell logs github-demo --since 5m --source sandbox
|
|
```
|
|
|
|
You should see a denial for a request resembling this one:
|
|
|
|
```text
|
|
[1775014140.412] [sandbox] [OCSF ] [ocsf] HTTP:POST [MED] DENIED POST http://github.com:443/<org>/<repo>.git/git-receive-pack [policy:_provider_my_github engine:l7] [reason:L7_REQUEST deny POST github.com:443/<org>/<repo>.git/git-receive-pack reason=POST /<org>/<repo>.git/git-receive-pack not permitted by policy]
|
|
```
|
|
|
|
`_provider_my_github` is the rule that OpenShell composes from the attached
|
|
`my-github` provider. Policy events are INFO-level log records, so do not filter
|
|
them out with `--level warn`.
|
|
|
|
You can also run `openshell term` to inspect policy decisions in the terminal
|
|
dashboard.
|
|
|
|
## Create a Repository-Scoped Policy
|
|
|
|
`policy set` replaces the complete base policy, so start from the sandbox's
|
|
current one. In terminal 2, print it:
|
|
|
|
```shell
|
|
openshell policy get github-demo --base
|
|
```
|
|
|
|
The command prints revision details followed by the policy. Save only the policy
|
|
YAML as `github-push.yaml`. Keep its filesystem, Landlock, and process settings
|
|
unchanged, because OpenShell rejects removed filesystem paths and changed
|
|
Landlock or process settings on a running sandbox.
|
|
|
|
Add these entries under `network_policies`, creating the section if it is
|
|
missing. Replace `<org>` and `<repo>`, and adjust `binaries` to match your
|
|
image:
|
|
|
|
```yaml
|
|
network_policies:
|
|
github_repository_push:
|
|
name: github-repository-push
|
|
endpoints:
|
|
- host: github.com
|
|
port: 443
|
|
protocol: rest
|
|
enforcement: enforce
|
|
rules:
|
|
- allow:
|
|
method: GET
|
|
path: "/<org>/<repo>.git/info/refs*"
|
|
- allow:
|
|
method: POST
|
|
path: "/<org>/<repo>.git/git-upload-pack"
|
|
- allow:
|
|
method: POST
|
|
path: "/<org>/<repo>.git/git-receive-pack"
|
|
binaries:
|
|
- path: /usr/bin/git
|
|
- path: /usr/local/bin/git
|
|
|
|
github_repository_api:
|
|
name: github-repository-api
|
|
endpoints:
|
|
- host: api.github.com
|
|
port: 443
|
|
protocol: rest
|
|
enforcement: enforce
|
|
rules:
|
|
- allow:
|
|
method: "*"
|
|
path: "/repos/<org>/<repo>/**"
|
|
binaries:
|
|
- path: /usr/bin/gh
|
|
- path: /usr/local/bin/gh
|
|
```
|
|
|
|
The first entry grants Git Smart HTTP operations only for the selected
|
|
repository. The second lets `gh` use REST operations scoped to the same
|
|
repository. The attached GitHub provider continues to supply credential
|
|
placement and its broader read-only rules.
|
|
|
|
## Apply the Policy
|
|
|
|
Apply the policy and wait for the new revision to load:
|
|
|
|
```shell
|
|
openshell policy set github-demo --policy github-push.yaml --wait
|
|
```
|
|
|
|
Network policy changes hot-reload without recreating the sandbox. Provider
|
|
rules are composed with this user-authored base policy.
|
|
|
|
## Retry and Verify
|
|
|
|
Ask the agent to retry the push. Then confirm that the proxy allowed the scoped
|
|
request:
|
|
|
|
```shell
|
|
openshell logs github-demo --since 5m
|
|
openshell policy get github-demo --full
|
|
```
|
|
|
|
The push succeeds for the selected repository. Requests to push to another
|
|
repository remain denied.
|
|
|
|
## Clean Up
|
|
|
|
Delete the sandbox when you are finished:
|
|
|
|
```shell
|
|
openshell sandbox delete github-demo
|
|
```
|
|
|
|
</Steps>
|
|
|
|
## Next Steps
|
|
|
|
- Review [Profiles](/how-it-works/providers/profiles) for endpoint-scoped credential placement.
|
|
- Review [Manage Sandbox Policies](/how-it-works/policies/manage-policies) for incremental policy updates and policy history.
|
|
- Review the [Policy Schema](/how-it-works/policies/schema) for REST, GraphQL, and other protocol rules.
|