AWS CodeArtifact Setup Guide for uv

2025-08-08 - 12 min read
Daniel Young
Daniel Young
Founder, DRYCodeWorks

Learn how to configure uv to install Python packages from AWS CodeArtifact using keyring for secure token management. This complete guide covers setup, daily usage, troubleshooting, and best practices.

AWS CodeArtifact Setup Guide for uv

This guide explains how to configure uv to install Python packages from AWS CodeArtifact using keyring for secure token management.

Prerequisites

  • Python 3.8+ installed
  • uv installed (installation guide)
  • AWS CLI configured with appropriate credentials
  • Access to your organization's CodeArtifact repository

Initial Setup (One-time)

1. Install Keyring with CodeArtifact Support

bash
uv tool install keyring --with keyrings.codeartifact

This installs the keyring tool globally, allowing secure storage of authentication tokens.

2. Configure Your Project

Add the following to your pyproject.toml:

pyproject.tomltoml
[tool.uv]
keyring-provider = "subprocess"

[[tool.uv.index]]
name = "your-index-name"
url = "https://your-domain-ACCOUNTID.d.codeartifact.REGION.amazonaws.com/pypi/your-repo/simple/"

Replace:

  • your-index-name: A descriptive name for your index (e.g., company-pypi)
  • your-domain: Your CodeArtifact domain name
  • ACCOUNTID: Your AWS account ID
  • REGION: Your AWS region (e.g., us-east-2)
  • your-repo: Your CodeArtifact repository name

3. Set Environment Variable

The environment variable name follows the pattern: UV_INDEX_<INDEX_NAME>_USERNAME

⚠️ Critical: Environment Variable Naming

The environment variable name must exactly match your index name from pyproject.toml:

  • Convert to uppercase
  • Replace hyphens with underscores
  • Use the exact same name you defined in [[tool.uv.index]]

This is the most common source of authentication failures!

bash
# For index named "your-index-name", use YOUR_INDEX_NAME (uppercase, hyphens become underscores)
export UV_INDEX_YOUR_INDEX_NAME_USERNAME=aws

# Add to your shell profile for persistence
echo 'export UV_INDEX_YOUR_INDEX_NAME_USERNAME=aws' >> ~/.zshrc  # or ~/.bashrc
source ~/.zshrc

Example: If your index is named company-pypi, the variable would be UV_INDEX_COMPANY_PYPI_USERNAME

4. Store Authentication Token

bash
aws codeartifact get-authorization-token \
  --domain your-domain \
  --domain-owner ACCOUNTID \
  --region REGION \
  --query authorizationToken \
  --output text | keyring set https://your-domain-ACCOUNTID.d.codeartifact.REGION.amazonaws.com/pypi/your-repo/simple/ aws

Note: The URL in the keyring command must exactly match the URL in your pyproject.toml.

5. Verify Setup

bash
# Test the connection
uv sync

Daily Usage

Refreshing Tokens

CodeArtifact tokens expire after 12 hours. Add this function to your shell profile (~/.zshrc or ~/.bashrc):

~/.zshrc or ~/.bashrcbash
refresh_codeartifact() {
  aws codeartifact get-authorization-token \
      --domain your-domain \
      --domain-owner ACCOUNTID \
      --region REGION \
      --query authorizationToken \
      --output text | keyring set https://your-domain-ACCOUNTID.d.codeartifact.REGION.amazonaws.com/pypi/your-repo/simple/ aws
  
  if [ $? -eq 0 ]; then
      echo "✓ CodeArtifact token refreshed at $(date '+%I:%M %p')"
  else
      echo "❌ Failed to refresh token"
      return 1
  fi
}

Then use:

bash
# Refresh token (needed every 12 hours)
refresh_codeartifact

# Work normally
uv sync
uv add package-name
uv remove package-name

Example Configuration

Here's a complete example for a company using CodeArtifact:

pyproject.toml:

pyproject.tomltoml
[project]
name = "my-project"
version = "0.1.0"
dependencies = [
  "requests>=2.31.0",
  "internal-package>=1.0.0",  # From CodeArtifact
]

[tool.uv]
keyring-provider = "subprocess"

[[tool.uv.index]]
name = "company"
url = "https://company-123456789012.d.codeartifact.us-east-1.amazonaws.com/pypi/internal/simple/"

Shell profile (~/.zshrc or ~/.bashrc):

~/.zshrc or ~/.bashrcbash
# CodeArtifact configuration
export UV_INDEX_COMPANY_USERNAME=aws

refresh_codeartifact() {
  aws codeartifact get-authorization-token \
      --domain company \
      --domain-owner 123456789012 \
      --region us-east-1 \
      --query authorizationToken \
      --output text | keyring set https://company-123456789012.d.codeartifact.us-east-1.amazonaws.com/pypi/internal/simple/ aws
  
  if [ $? -eq 0 ]; then
      echo "✓ Token refreshed successfully"
  else
      echo "❌ Token refresh failed"
      return 1
  fi
}

Troubleshooting

Authentication Errors

1. Verify environment variable is set

bash
echo $UV_INDEX_YOUR_INDEX_NAME_USERNAME
# Should output: aws

2. Check token is stored in keyring

bash
keyring get https://your-url/simple/ aws | head -c 20
# Should show start of token

3. Ensure AWS CLI is configured

bash
aws sts get-caller-identity
# Should show your AWS identity

4. Run with verbose output

bash
uv sync -v

Common Issues

IssueSolution
401 UnauthorizedToken expired - run refresh_codeartifact
Token not found in keyringURL in keyring command doesn't match pyproject.toml exactly
Environment variable not foundCheck spelling and uppercase conversion (hyphens → underscores)
AWS CLI errorsVerify AWS credentials and permissions
Keychain access errors (macOS)Grant Terminal/Python access in Keychain Access app

Required IAM Permissions

Ensure your AWS user/role has these permissions:

iam-policy.jsonjson
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Effect": "Allow",
          "Action": [
              "codeartifact:GetAuthorizationToken",
              "sts:GetServiceBearerToken"
          ],
          "Resource": "*"
      },
      {
          "Effect": "Allow",
          "Action": "codeartifact:ReadFromRepository",
          "Resource": "arn:aws:codeartifact:REGION:ACCOUNTID:repository/your-domain/your-repo"
      }
  ]
}

Quick Setup Script

Save this as setup_codeartifact.sh and customize for your organization:

setup_codeartifact.shbash
#!/bin/bash

# Configuration - CUSTOMIZE THESE
DOMAIN="your-domain"
ACCOUNT_ID="123456789012"
REGION="us-east-1"
REPO="your-repo"
INDEX_NAME="YOUR_INDEX_NAME"  # Uppercase, underscores instead of hyphens

# Colors for output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m'

echo -e "${BLUE}Setting up CodeArtifact...${NC}"

# Install keyring
echo -e "${BLUE}Installing keyring...${NC}"
uv tool install keyring --with keyrings.codeartifact

# Set environment variable
export UV_INDEX_${INDEX_NAME}_USERNAME=aws
echo -e "${GREEN}✓ Environment variable set${NC}"

# Store token
echo -e "${BLUE}Storing authentication token...${NC}"
URL="https://${DOMAIN}-${ACCOUNT_ID}.d.codeartifact.${REGION}.amazonaws.com/pypi/${REPO}/simple/"

aws codeartifact get-authorization-token \
  --domain $DOMAIN \
  --domain-owner $ACCOUNT_ID \
  --region $REGION \
  --query authorizationToken \
  --output text | keyring set $URL aws

if [ $? -eq 0 ]; then
  echo -e "${GREEN}✓ Setup complete! You can now run: uv sync${NC}"
else
  echo -e "${RED}Setup failed. Check your AWS credentials.${NC}"
  exit 1
fi

Platform-Specific Notes

macOS

  • If you encounter keychain access errors, open Keychain Access app and grant Terminal/Python access
  • You may need to unlock your keychain: security unlock-keychain ~/Library/Keychains/login.keychain-db

Linux

  • keyring will use the Secret Service API (GNOME Keyring or KDE Wallet)
  • Ensure your desktop environment's keyring service is running

Windows

  • keyring uses Windows Credential Manager
  • Access via Control Panel → User Accounts → Credential Manager

CI/CD Environments

For automated environments, use environment variables instead of keyring:

GitHub Actions exampleyaml
env:
UV_INDEX_COMPANY_USERNAME: aws
UV_INDEX_COMPANY_PASSWORD: ${{ secrets.CODEARTIFACT_TOKEN }}
GitLab CI exampleyaml
variables:
UV_INDEX_COMPANY_USERNAME: aws
UV_INDEX_COMPANY_PASSWORD: ${CODEARTIFACT_TOKEN}

Security Best Practices

  • Never commit tokens to version control
  • Use IAM roles when possible instead of IAM users
  • Rotate tokens regularly (they expire every 12 hours by default)
  • Limit IAM permissions to only what's needed
  • Use separate repositories for different projects/teams
  • Enable CloudTrail logging for CodeArtifact API calls

Support Resources

For issues specific to:


Last updated: August 2025
Version: 1.0