# How ipsw Automates App Store Connect Certificate and Provisioning Profile Management

> Automate App Store Connect certificate and provisioning profile management with ipsw. Streamline your workflow using its Go library or CLI for creation, listing, and deletion.

- Repository: [blacktop/ipsw](https://github.com/blacktop/ipsw)
- Tags: how-to-guide
- Published: 2026-02-26

---

**ipsw provides a built-in App Store Connect client that automates certificate and provisioning profile creation, listing, and deletion through both a Go library API and a comprehensive CLI interface.**

The `blacktop/ipsw` open-source tool streamlines iOS and macOS development workflows by exposing Apple's App Store Connect API through high-level commands. Whether you need to generate signing certificates, manage provisioning profiles, or automate device registration, ipsw eliminates the need for manual portal navigation by implementing the full certificate and provisioning profile lifecycle in code.

## Core App Store Connect API Client

At the foundation of ipsw's App Store Connect capabilities lies the `AppStore` struct defined in [`pkg/appstore/appstore.go`](https://github.com/blacktop/ipsw/blob/main/pkg/appstore/appstore.go). This core client handles authentication, JWT token generation, and HTTP communication with Apple's API endpoints.

The `NewAppStore` constructor initializes the client with your API key (`.p8` file), issuer ID, and key ID, automatically handling JWT signing for authenticated requests. All subsequent operations—`CreateCertificate`, `GetCertificates`, `CreateProfile`, `GetProfiles`, and `GetBundleID`—build upon this authenticated session, providing a consistent interface for App Store Connect interactions.

## Automated Provisioning Workflow

The `ProvisionSigningFiles` function in [`pkg/appstore/provision.go`](https://github.com/blacktop/ipsw/blob/main/pkg/appstore/provision.go) orchestrates the complete signing asset generation process. This high-level workflow automates what traditionally requires multiple manual steps in the Apple Developer portal.

### Certificate Handling

The `ensureCertificate` helper manages the entire certificate lifecycle. When invoked, it first queries existing certificates via `GetCertificates` to locate a valid, unexpired match. If no suitable certificate exists, ipsw generates a 2048-bit RSA private key, constructs a Certificate Signing Request (CSR), and submits it to `CreateCertificate`. The resulting private key is persisted to your output directory (e.g., `development_private_key.pem`) for subsequent signing operations.

### Provisioning Profile Management

The `ensureProvisioningProfile` function handles profile creation and validation. It resolves the target bundle identifier, fetches registered devices for Development or AdHoc profiles, and searches for existing active profiles matching your certificate and bundle ID. When no valid profile exists, it automatically creates a new one through the App Store Connect API, ensuring your signing assets remain synchronized with your current device list and certificates.

### Local Installation

When the `--install` flag is specified, ipsw imports generated assets directly into your development environment. `InstallCertificateAndKey` adds the certificate and private key to the macOS Keychain, while `InstallProvisioningProfile` copies the `.mobileprovision` file to `~/Library/MobileDevice/Provisioning Profiles/`, making the assets immediately available to Xcode.

## CLI Commands for App Store Connect Management

ipsw exposes its App Store Connect functionality through a hierarchical CLI structure built with Cobra, located in `cmd/ipsw/cmd/appstore/`. All subcommands inherit global authentication flags (`--p8`, `--iss`, `--kid`, `--jwt`) defined in [`cmd/ipsw/cmd/appstore/appstore.go`](https://github.com/blacktop/ipsw/blob/main/cmd/ipsw/cmd/appstore/appstore.go).

### Certificate Commands

- **`ipsw appstore cert add`** ([`appstore_cert_add.go`](https://github.com/blacktop/ipsw/blob/main/appstore_cert_add.go)): Creates a new certificate from a provided CSR or generates one automatically. Supports specifying certificate types (development, distribution).
- **`ipsw appstore cert ls`**: Lists all certificates associated with your team, displaying expiration dates and certificate IDs.
- **`ipsw appstore cert rm`**: Revokes certificates by ID, immediately invalidating associated provisioning profiles.

### Provisioning Profile Commands

- **`ipsw appstore profile create`** ([`appstore_profile_create.go`](https://github.com/blacktop/ipsw/blob/main/appstore_profile_create.go)): Invokes `ProvisionSigningFiles` to generate both certificates and profiles in a single command. Accepts parameters for bundle ID, profile type, and output directory.
- **`ipsw appstore profile ls`**: Enumerates active and expired provisioning profiles with their associated certificates and entitlements.
- **`ipsw appstore profile renew`**: Regenerates existing profiles with updated device lists or certificates without changing the profile UUID.
- **`ipsw appstore profile rm`** ([`appstore_profile_rm.go`](https://github.com/blacktop/ipsw/blob/main/appstore_profile_rm.go)): Deletes provisioning profiles from App Store Connect.

### Device and Bundle ID Helpers

Supporting commands in [`cmd/ipsw/cmd/appstore/appstore_device_ls.go`](https://github.com/blacktop/ipsw/blob/main/cmd/ipsw/cmd/appstore/appstore_device_ls.go) and related files enable device registration and bundle ID enumeration. These helpers automatically populate device lists when creating Development or AdHoc profiles, ensuring new test devices are included without manual portal updates.

## Code Examples

### Using the Go Library

You can integrate ipsw's App Store Connect client directly into your Go applications:

```go
import (
    "log"
    "github.com/blacktop/ipsw/pkg/appstore"
)

func main() {
    // Initialise the API client (p8, iss, kid or JWT)
    as := appstore.NewAppStore("AuthKey_ABC123.p8", "12345678-1234-1234-1234-123456789ABC", "ABCDEF1234", "")

    // Build the provisioning request
    cfg := &appstore.ProvisionSigningFilesConfig{
        CertType: "distribution",   // development | adhoc | distribution
        BundleID: "com.example.myapp",
        CSR:      true,             // generate a new key/CSR
        Email:    "dev@example.com",
        Country:  "US",
        Install:  true,             // import into keychain & profile folder
        Output:   "./signing-assets",
    }

    // This will create (or reuse) the cert + profile and install them
    if err := as.ProvisionSigningFiles(cfg); err != nil {
        log.Fatalf("Provisioning failed: %v", err)
    }
}

```

### Using the Command-Line Interface

Generate a complete signing set for App Store distribution:

```bash

# Generate (or reuse) a distribution certificate & App‑Store profile,

# write them to ./assets and install them locally.

ipsw appstore provision \
    --type distribution \
    --bundle-id com.example.myapp \
    --email dev@example.com \
    --country US \
    --output ./assets \
    --install

```

Create a certificate from a pre-generated CSR:

```bash

# Assume my.csr contains a PEM‑encoded CSR

ipsw appstore cert add \
    --type development \
    --csr "$(cat my.csr)" \
    --output ./certs

```

## Summary

- **ipsw** implements a complete App Store Connect client in [`pkg/appstore/appstore.go`](https://github.com/blacktop/ipsw/blob/main/pkg/appstore/appstore.go), handling JWT authentication and API communication.
- The `ProvisionSigningFiles` function in [`pkg/appstore/provision.go`](https://github.com/blacktop/ipsw/blob/main/pkg/appstore/provision.go) automates the entire workflow: RSA key generation, CSR creation, certificate issuance, provisioning profile creation, and local installation.
- CLI commands under `cmd/ipsw/cmd/appstore/` provide granular control over certificates (`cert add/ls/rm`) and profiles (`profile create/ls/renew/rm`).
- The tool supports both library integration (Go API) and command-line automation, enabling CI/CD pipelines to manage signing assets without manual Apple Developer portal interaction.

## Frequently Asked Questions

### How does ipsw authenticate with App Store Connect?

ipsw authenticates using JWT (JSON Web Tokens) signed with your private API key. The `NewAppStore` constructor in [`pkg/appstore/appstore.go`](https://github.com/blacktop/ipsw/blob/main/pkg/appstore/appstore.go) accepts your `.p8` key file path, issuer ID, and key ID, then automatically generates and signs JWTs for each API request. Alternatively, you can provide a pre-generated JWT string via the `--jwt` flag.

### Can ipsw generate private keys and CSRs automatically?

Yes. When the `CSR` field is set to `true` in the `ProvisionSigningFilesConfig` (or when using the `--csr` flag in the CLI), ipsw generates a 2048-bit RSA private key and constructs a Certificate Signing Request (CSR) automatically. The private key is saved to your specified output directory (e.g., `development_private_key.pem`), and the CSR is submitted to Apple's servers to create the certificate.

### What is the difference between `ipsw appstore cert` and `ipsw appstore profile` commands?

The `cert` subcommands manage **certificates** (the cryptographic identities used to sign code), while the `profile` subcommands manage **provisioning profiles** (which link certificates, bundle IDs, and devices). Specifically, `cert add` creates signing certificates from CSRs, `cert ls` lists them, and `cert rm` revokes them. Conversely, `profile create` generates provisioning profiles (and can create accompanying certificates automatically), `profile ls` lists profiles, and `profile rm` deletes them.

### Does ipsw support installing certificates directly into the macOS keychain?

Yes. When you set `Install: true` in the Go library's `ProvisionSigningFilesConfig` or use the `--install` flag in the CLI, ipsw automatically imports the generated certificate and private key into the macOS Keychain using the `InstallCertificateAndKey` function. It also copies provisioning profiles to `~/Library/MobileDevice/Provisioning Profiles/` via `InstallProvisioningProfile`, making the assets immediately available to Xcode without manual import steps.