# Construct Hub
This project maintains a [AWS Cloud Development Kit](https://github.com/aws/aws-cdk) construct library
that can be used to deploy instances of the Construct Hub in any AWS Account.
This software backs the public instance of the
[ConstructHub](https://constructs.dev), and can be used to deploy a self-hosted
instance with personalized configuration.
## :question: Getting Started
> :warning: Disclaimer
>
> The [public instance of ConstructHub](https://constructs.dev) is currently in
> *Developer Preview*.
>
> Self-hosted ConstructHub instances are however in active development and
> should be considered *experimental*. Breaking changes to the public API of
> this package are expected to be released without prior notice, and the
> infrastructure and operational posture of ConstructHub instances may also
> significantly change.
>
> You are welcome to deploy self-hosted instances of ConstructHub for evaluation
> purposes, and we welcome any feedback (good or bad) from your experience in
> doing so.
### Quick Start
Once you have installed the `construct-hub` library in your project, the
simplest way to get started is to create an instance of the `ConstructHub`
construct:
```python
# Example automatically generated from non-compiling source. May contain errors.
import { App, Stack } from '@aws-cdk/core';
import { ConstructHub } from 'construct-hub';
// The usual... you might have used `cdk init app` instead!
const app = new App();
const stack = new Stack(app, 'StackName', { /* ... */ });
// Now to business!
new ConstructHub(stack, 'ConstructHub');
```
### Personalization
#### Using a custom domain name
In order to use a custom domain for your ConstructHub instance instead of the
default CloudFront domain name, specify the `domain` property with the following
elements:
Attribute | Description
------------------------------|---------------------------------------------------------------------
`zone` | A Route53 Hosted Zone, where DNS records will be added.
`cert` | An Amazon Certificate Manager certificate, which must be in the `us-east-1` region.
`monitorCertificateExpiration`| Set to `false` if you do not want an alarm to be created when the certificate is close to expiry.
Your self-hosted ConstructHub instance will be served from the root of the
provided `zone`, so the certificate must match this name.
#### Alternate package sources
By default, ConstructHub has a single package source configured: the public
`npmjs.com` registry. Self-hosted instances typically should list packages from
alternate sources, either in addition to packages from `npmjs.com`, or instead
of those.
The `packageSources` property can be used to replace the default set of package
sources configured on the instance. ConstructHub provides `IPackageSource`
implementations for the public `npmjs.com` registry as well as for private
CodeArtifact repositories:
```python
# Example automatically generated from non-compiling source. May contain errors.
import * as codeartifact from '@aws-cdk/aws-codeartifact';
import { App, Stack } from '@aws-cdk/core';
import { sources, ConstructHub } from 'construct-hub';
// The usual... you might have used `cdk init app` instead!
const app = new App();
const stack = new Stack(app, 'StackName', { /* ... */ });
// Now to business!
const registry = new codeartifact.CfnRegistry(stack, 'Registry', {
// ....
});
new ConstructHub(stack, 'ConstructHub', {
packageSources: [
new sources.NpmJs(), // Remove if you do NOT want npmjs.com packages
new sources.CodeArtifact({ registry }),
],
});
```
You may also implement a custom `IPackageSource` if you want to index packages
from alternate locations. In this case, the component you provide will be
responsible for sending notifications to an SQS Queue about newly discovered
packages. You may refer to the [sources.NpmJs](src/package-sources/npmjs.ts) and [sources.CodeArtifact](src/package-sources/code-artifact.ts)
implementations as a reference for hos this can be done.
By default, download counts of NPM packages will be fetched periodically from
NPM's public API by a Lambda. Since this is not desirable if you are using a
private package registry, this is automatically disabled if you specify your own
value for `packageSources`. (But this can be re-enabled through the
`fetchPackageStats` property if needed).
#### Package deny list
Certain packages may be undesirable to show in your self-hosted ConstructHub
instance. In order to prevent a package from ever being listed in construct hub,
the `denyList` property can be configured with a set of `DenyListRule` objects
that specify which package or package versions should never be lested:
```python
# Example automatically generated from non-compiling source. May contain errors.
import { App, Stack } from '@aws-cdk/core';
import { ConstructHub } from 'construct-hub';
// The usual... you might have used `cdk init app` instead!
const app = new App();
const stack = new Stack(app, 'StackName', { /* ... */ });
// Now to business!
new ConstructHub(stack, 'ConstructHub', {
denyList: [
// Denying _all_ versions of the "sneaky-hackery" package
{ packageName: 'sneaky-hackery', reason: 'Mines bitcoins wherever it gets installed' },
// Denying _a specific_ version of the "bad-release" package
{ packageName: 'bad-release', version: '1.2.3', reason: 'CVE-####-#####' },
],
});
```
#### Redirecting from additional domains
You can add additional domains that will be redirected to your primary Construct
Hub domain:
```python
# Example automatically generated from non-compiling source. May contain errors.
import * as r53 from '@aws-cdk/aws-route53';
const myDomainZone = r53.HostedZone.fromHostedZoneAttributes(this, 'MyDomainZone', {
hostedZoneId: 'AZ1234',
zoneName: 'my.domain.com',
});
new ConstructHub(this, 'ConstructHub', {
additionalDomains: [ { hostedZone: myDomainZone } ]
});
```
This will set up full domain redirect using Amazon S3 and Amazon CloudFront. All
requests will be redirected to your primary Construct Hub domain.
#### Decrease deployment footprint
By default, ConstructHub executes the documentation rendering process in the
context of isolated subnets. This is a defense-in-depth mechanism to mitigate
the risks associated with downloading aribtrary (un-trusted) *npm packages* and
their dependency closures.
This layer of security implies the creation of a number of resources that can
increase the operating cost of your self-hosted instance: several VPC endpoints
are created, an internal CodeArtifact repository needs to be provisioned, etc...
While we generally recommend leaving these features enabled, if your self-hosted
ConstructHub instance only indexes *trusted* packages (as could be the case for
an instance that does not list packages from the public `npmjs.com` registry),
you may set the `isolateLambdas` setting to `false`.
## :gear: Operating a self-hosted instance
1. [Application Overview](./docs/application-overview.md) provides a high-level
description of the components that make a ConstructHub instance. This is a
great starting point for people who consider operating a self-hosted instance
of ConstructHub; and for new operators on-boarding the platform.
2. [Operator Runbook](./docs/operator-runbook.md) is a series of diagnostics and
troubleshooting guides indended for operators to have a quick and easy way to
navigate a ConstructHub instance when they are reacting to an alarm or bug
report.
### :baby_chick: Deployment Canaries
Construct Hub provides several built-in validation mechanisms to make sure the
deployment of your instance is continuously operating as expected.
These mechanisms come in the form of canary testers that are part of the
ConstructHub deployment stack. Each canary runs periodically and performs a
different check, triggering a different CloudWatch alarm in case it detects a
failu