GithubHelp home page GithubHelp logo

notaryproject / notation-core-go Goto Github PK

View Code? Open in Web Editor NEW
13.0 13.0 28.0 274 KB

Contains support for Notary Project signature envelope, and format specific implementation

License: Apache License 2.0

Go 99.63% Makefile 0.37%

notation-core-go's Introduction

Notary Project Specifications

This repository is in active maintenance and contains specifications shared across repositories under Notary Project as well as used by other open source projects and/or vendor tools that want to interoperate with Notary Project tooling.

Please see the Notary Project README file to learn about overall Notary Project.

In this README

Folder Structure

Folder Name Description
media Media files referenced by documents in this repository
requirements Requirements for Notary Project
security Notary Project security related documents and reports
specs Notary Project specifications
status-updates This folder is not in active maintenance and contains status updates report for Notary Project
threatmodels Threat models for repositories under Notary Project

Requirements

File Name Description
definitions-terms.md A collection of definitions and terms used within this repository
key-revocation.md Requirements and proposals for key revocation
keymanagementrequirements.md Requirements for key management
requirements.md A collection of requirements and scenarios for Notary Project
scenarios.md Notary Project signing scenarios
verification-by-reference.md Requirement of verification by reference

Security Documents

File Name Description
ADA-notation-security-audit-23.pdf Security audit report in 2023 covering notation, notation-go, and notation-core-go repositories
ADA-fuzzing-audit-22-23.pdf Fuzz testing audit in 2023 covering notary, notation-go, and notation-core-go repositories

Specifications

File Name Description
plugin-extensibility.md Notation Plugin specification
signature-envelope-cose.md Notary Project OCI COSE signature envelope
signature-envelope-jws.md Notary Project OCI JWS signature envelope
signature-specification.md Notary Project OCI signature specification
signing-and-verification-workflow.md Notary Project OCI signing and verification workflow
signing-scheme.md Notary Project signing scheme
trust-store-trust-policy.md Notary Project Trust Store and Trust Policy

Threat Models

File Name Description
notation-threatmodel.md Threat models for Notation CLI

Community

If you have any questions about Notary Project or contributing, do not hesitate to file an issue on relevant repository or contact the Notary Project maintainers and community members via the following channels:

notation-core-go's People

Contributors

binbin-li avatar chloeyin avatar dependabot[bot] avatar fanndu avatar jeyjeygao avatar jondonas avatar junczhu avatar kody-kimberl avatar priteshbandi avatar rgnote avatar shizhmsft avatar stevelasker avatar toddysm avatar two-hearts avatar wwwsylvia avatar yizha1 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

notation-core-go's Issues

bug: fail to verify COSE signature with extra attributes in the protected header

When the COSE signature contains extra attribute keys, which are integers not strings, the code reports error:

extendedAttributes key requires string type

Those keys should be ignored if not marked as critical, or report error if marked as critical. If they are known attributes, we may convert keys into strings so that it can fill in the signature.Attribute structure.

Related code:

// fetch all the extended signed attributes
systemHeaders := []interface{}{cose.HeaderLabelAlgorithm, cose.HeaderLabelCritical, cose.HeaderLabelContentType,
headerLabelExpiry, headerLabelSigningScheme, headerLabelSigningTime, headerLabelAuthenticSigningTime}
var extendedAttributeKeys []string
for label := range protected {
if contains(systemHeaders, label) {
continue
}
label, ok := label.(string)
if !ok {
return nil, &signature.InvalidSignatureError{Msg: "extendedAttributes key requires string type"}
}
extendedAttributeKeys = append(extendedAttributeKeys, label)
}

vote: tag 1.0.0

Release

This would mean tagging 0c1ec3b as v1.0.0 to release.

Vote

We need at least 4 approvals from 6 maintainers to release notation-core-go v1.0.0.

Changes

The code changes compared to v1.0.0-rc.4 include:

Full Changelog: v1.0.0-rc.4...0c1ec3b

Action Requested

Please respond LGTM or REJECT (with reasoning).

self-signed leaf cert validation issue

We didn’t check the issuer of the self-signed leaf certificate. The self-signed leaf certificate should also be self-issued.

if len(certChain) == 1 {
cert := certChain[0]
if signingTime != nil && (signingTime.Before(cert.NotBefore) || signingTime.After(cert.NotAfter)) {
return fmt.Errorf("certificate with subject %q was not valid at signing time of %s", cert.Subject, signingTime.UTC())
}
if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
return fmt.Errorf("invalid self-signed certificate. subject: %q. Error: %w", cert.Subject, err)
}
if err := validateLeafCertificate(cert, expectedLeafEku); err != nil {
return fmt.Errorf("invalid self-signed certificate. Error: %w", err)
}
return nil
}

Reducing the PR approval count to 2

What is the areas you experience the issue in?

Notation CLI

What is not working as expected?

To increase the velocity of the development, we would like to reduce the PR approval count to 2. The justification is the following: with the current count of 3 approvals we have 4 people who need to be involved in the PR. Our initial goal was to have min 3. By reducing to 2 approvals required we still have 3 people including the original submitter.

What did you expect to happen?

Reduce PR approvals to 2

How can we reproduce it?

N/A

Describe your environment

N/A

What is the version of your Notation CLI or Notation Library?

N/A

Temporarily bypassing status check for #135

The PR #135 is to shift the golang support window to [1.19, 1.20]. Although we've got sufficient approvals, we are not able to merged PR since the check for golang 1.18 is removed, which is intended.

image

To merge the PR, we need to temporarily uncheck the "Do not allow bypassing the above settings" for the main branch to bypass the build check.

image

Of course, it is also can be done by unchecking "Require branches to be up to date before merging" but I think unchecking the "Do not allow bypassing the above settings" is safer.

@notaryproject/notaryproject-notation-core-go-maintainers Please reply LGTM to proceed or comment for suggestions.

CMS package

Is your feature request related to a problem?

Timestamping support needs CMS package

What solution do you propose?

  • BER to DER converter
  • CMS package

What alternatives have you considered?

No

Any additional context?

No response

Key usage error message

What is not working as expected?

Error: certificate-chain is invalid, invalid self-signed certificate. Error: certificate with subject "CN=xx.com,O=Notary,L=xx,ST=CA,C=US": key usage must not have the bit positions for ContentCommitment, KeyEncipherment, DataEncipherment, KeyAgreement, CertSign, CRLSign, EncipherOnly, DecipherOnly set

If the certificate has more key usages than DigitalSignature, the error message will display all the other key usages. However, this can be confusing if the user didn't set those key usages.

What did you expect to happen?

The error message should either state that there should be only one DigitalSignature key usage or mention the specific key usages that the certificate actually has and should not exist, instead of all of them.

How can we reproduce it?

sign with a certificate that has unnecessary key usages

Describe your environment

Linux

What is the version of your notation-core-go Library?

v1.0.0

Proposal to update the CODEOWNERS file and add MAINTAINERS file

What is the areas you would like to add the new feature to?

Notation Core Go

Is your feature request related to a problem?

The current content of the CODEOWERS file does not list the actual owners and points to a Team on GitHub. This does not provide enough visibility who the owners are.

What solution do you propose?

The proposal is to create a seed list of maintainers for each repository (aka considered sub-project) under the Notary Project organization and update the CODEOWNERS and MAINTAINERS files for each repository with that list. As per the current governance document:

Potential new maintainers should be ongoing active participants in the project

Hence, I propose that repo maintainers are proposed from the list of currently active participants in the Notary community by selecting them from the list of code contributors for the last 3-6 months or meeting participants as per the meeting notes.

I also propose to nominate individual maintainers in separate issues and put for a vote by the active participants' community.

What alternatives have you considered?

None

Any additional context?

No response

error message may not right

In line 67 of the code, if i == 0 which is the leaf cert, the error message still says that it is the intermediate certificate, so the error message may not right. It may need to return the CommonName of the cert to help use identify the invalid cert.

for i, cert := range certChain {
if signingTime != nil && (signingTime.Before(cert.NotBefore) || signingTime.After(cert.NotAfter)) {
return fmt.Errorf("certificate with subject %q was not valid at signing time of %s", cert.Subject, signingTime.UTC())
}
if i == len(certChain)-1 {
if !isSelfSigned(cert) {
return errors.New("certificate chain must end with a root certificate (root certificates are self-signed)")
}
} else {
// This is to avoid extra/redundant multiple root cert at the end of certificate-chain
if isSelfSigned(cert) {
return errors.New("certificate chain must not contain self-signed intermediate certificates")
} else if nextCert := certChain[i+1]; !isIssuedBy(cert, nextCert) {
return fmt.Errorf("certificate with subject %q is not issued by %q", cert.Subject, nextCert.Subject)
}
}
if i == 0 {
if err := validateLeafCertificate(cert, expectedLeafEku); err != nil {
return err
}
} else {

Refactor on SignRequest

Background

In the PR, we introduced VerificationPlugin and VerificationPluginMinVersion to the SignRequest to support validate them in the notation-core-go.

Problem

  1. As specified in specs: Extended attributes for Notation Plugins and Extended Protected Headers for Notation Plugins, VerificationPlugin and VerificationPluginMinVersion should be placed inside the ExtendedSignedAttrs of SignRequest.
  2. For the validation, according to Verification workflow using plugin, we can see that it's reasonable to group version validation and capability validation together once we retrieve the plugin metadata. However, current implementation puts version validation in notation-core-go and capability validation in notation-go. Besides it, part of version validation is placed in notation-go which made reviewers confused on the validation workflow.

Proposed refactoring

  1. Move VerificationPlugin and VerificationPluginMinVersion to ExtendedSignedAttrs of SignRequest.
  2. Move all version validation logics to notation-go, specifically version validation

Improve error messages for chain validations in cert_validations.go

The errors returned in cert_validations.go can sometimes be very long and may not be easily understood, for example:

invalid certificates or certificate with subject \"CN=Notation Test Revokable RSA Chain Cert 3,O=Notary,L=Seattle,ST=WA,C=US\" is not issued by \"CN=Notation Test Revokable RSA Chain Cert 4,O=Notary,L=Seattle,ST=WA,C=US\". Error: x509: invalid signature: parent certificate cannot sign this kind of certificate

We should look into returning errors with messages that are more understandable and not as long, which will help with readability. Below are some suggestions for improvements:

In the above example, we should programmatically differentiate between an invalid certificate or an incorrect issuer. This will improve the understandability of the unnecessary "or" at the beginning.

Additionally, we should consider alternatives for including the entire subject (maybe only CN and O, or referencing the numerical position of the cert in the chain)

Lastly, we should not include "Error: " when wrapping errors from other functions, only the error message

follow up on license checker version updates

Is your feature request related to a problem?

This is an issue to track the license checker version updates (in case dependabot does not detect a new release automatically).
Current workflow uses a commit hash of skywalking-eyes to fix the weak-compatible issue of notation-core-go. Related PR: #170
This issue can be resolved when skywalking-eyes releases its next version with the fix included.

What solution do you propose?

n/a

What alternatives have you considered?

n/a

Any additional context?

No response

vote: tag 1.0.1

Release

This would mean tagging c834adc as v1.0.1 to release.

Vote

We need at least 4 approvals from 6 maintainers to release notation-core-go v1.0.1.

Changes

The code changes compared to v1.0.0 include:

Full Changelog: v1.0.0...c834adc

Action Requested

Please respond LGTM or REJECT (with reasoning).

The notation spec link in annotation is unavailable

What is not working as expected?

Eg.https://github.com/notaryproject/notaryproject/blob/main/signature-specification.md response 404, because of the notation spec had been moved to "specs" dir.

What did you expect to happen?

Update the spec links to the latest.

How can we reproduce it?

Update
https://github.com/notaryproject/notaryproject/blob/main/xxx.md to https://github.com/notaryproject/notaryproject/blob/main/specs/xxx.md
and
https://github.com/notaryproject/notaryproject/blob/main/trust-store-trust-policy-specification.md to https://github.com/notaryproject/notaryproject/blob/main/specs/trust-store-trust-policy.md

Describe your environment

N/A

What is the version of your notation-core-go Library?

N/A

Refactor code to support multiple envelopes

The package signer is tightly coupled with JWS signature envelope. To support other signature envelopes (e.g. COSE) in the future, we need to decouple the logic in the package signer at least into the following sub packages:

  • jws: Process the SignRequest and generate JWS signature envelope. Parse and verify JWS signature envelope.
  • cose: Process the SignRequest and generate COSE signature envelope. Parse and verify COSE signature envelope.
  • envelope: Common logic on processing all kinds of envelopes (e.g. JWS, COSE).

Proposals can be found at

doc: outline design for OCSP revocation

This issue outlines how the core revocation functionality will be built into notation-core-go, and how it will be integrated with notation-go. This additional functionality will provide a mechanism to check the revocation status of certificates in a way that can be easily integrated into other projects, and to conduct revocation checks as part of the Verify process.

These changes will address the following issue:

  • Implement OCSP Support (#124)

CRL Support will not be implemented until later.

The outlined mechanisms are based upon previously defined specifications (https://github.com/notaryproject/notaryproject/blob/main/specs/trust-store-trust-policy.md#certificate-revocation-evaluation) as well as some ideas from existing solutions (https://pkg.go.dev/github.com/cloudflare/cfssl/revoke and https://github.com/grpc/grpc-go/blob/52ca9571068d/security/advancedtls/crl.go) that don’t fully match our use case.

Implementation is planned to be completed in two PRs. The first will introduce the revocation package in notation-core-go. The second PR will follow, which will incorporate the revocation package into notation-go. These sections are separated by a horizontal line.


Notation-core-go

The following will be added as a new package within the x509 package via a new file, revocation.go:

// Internal struct
type revocation struct {
    httpClient            *http.Client
    ocspTimeoutThreshold  time.Duration
}

// Options struct
// Users can specify any options they want for constructing a revocation object
// If an option is unspecified or nil, a default value will be assigned in the NewRevocation function
type RevocationOptions struct {
    ocspTimeoutThreshold  time.Duration
}

// Constructor to return a revocation object that substitutes default values for any that are passed as nil
func NewRevocation(httpClient *http.Client, options RevocationOptions) *revocation


// Errors:
// RevokedInOCSPError is returned when the certificate's status for OCSP is ocsp.Revoked (or ocsp.Unknown?)
type RevokedInOCSPError struct{}
func (e RevokedInOCSPError) Error() string {
    return "certificate is revoked via OCSP"
}

// CheckOCSPError is returned when there is an error during the OCSP revocation check, not necessarily a revocation
type CheckOCSPError struct {
    Err error
}
func (e CheckOCSPError) Error() string {
    if e.Err != nil {
        return fmt.Sprintf("error checking revocation via OCSP: %s", e.Err.Error())
    } else {
        return "error checking revocation via OCSP"
    }
}

// NoOCSPServerError is returned when the OCSPServer is not specified or is not an HTTP URL.
type NoOCSPServerError struct{}
func (e NoOCSPServerError) Error() string {
    return "no valid OCSPServer found"
}

// OCSPTimeoutError is returned when the connection attempt to a OCSP URL exceeds the specified threshold
type OCSPTimeoutError struct{}
func (e OCSPTimeoutError) Error() string {
    return "exceeded timeout threshold for OCSP check"
}

// It may be necessary to add other errors to the ones specified as new errors/results are discovered during development

// Methods:
// Checks OCSP, then CRL status, returns nil if all certs in the chain are not revoked
// If any are revoked, it will return one of the defined errors in this file
// If there is some other error, it will return that error
// NOTE: Will only perform OCSP until CRL is implemented
func (r *revocation) Validate(certChain []*x509.Certificate) (error)

// Only checks OCSP, same returns as above
func (r *revocation) OCSPStatus(certChain []*x509.Certificate) (error)

Since testing this will require validating against OCSP server responses, a mock client needs to be created to mock these responses. This will be added to the testhelper package in a new file named httptest.go:

// Creates a mock HTTP Client (more accurately, a spy) that intercepts requests to /issuer and /ocsp endpoints
// The client's responses are dependent on the cert and desiredOCSPStatus
func MockClient(cert *x509.Certificate, key *rsa.PrivateKey, desiredOCSPStatus ocsp.ResponseStatus) *http.Client

In addition to the mocked client, we will also need a new test certificate that specifies an OCSPServer in the certificate template. This value will be necessary to confirm revocation status with the mocked client. The following will be added to the testhelper package in the existing certificatetest.go file:

var revokableRSALeaf RSACertTuple

// GetRevokableRSALeafCertificate returns leaf certificate that specifies a local OCSPServer signed using RSA algorithm
func GetRevokableRSALeafCertificate() RSACertTuple

Notation-go

The following will be added/modified in the verifier package within the existing verifier.go file:

// Since a section has already been added to Verify as a placeholder for revocation, it will be modified to incorporate the verifyRevocation function
func (v *verifier) Verify(ctx context.Context, desc ocispec.Descriptor, signature []byte, opts notation.VerifyOptions) (*notation.VerificationOutcome, error)

// The verifyRevocation function will use the revocation.Validate() function defined in notation-core-go to verify the revocation status
func verifyRevocation(outcome *notation.VerificationOutcome) *notation.ValidationResult

TypeRevocation has already been added to the ValidationTypes in the trustpolicy, so no change is needed there.

Check the license header for notation-core-go and its dependencies

Is your feature request related to a problem?

Consider if notation-core-go needs dependency license checking and reporting

What solution do you propose?

Consider adding dependency license checking and reporting similar to notaryproject/notation#706

What alternatives have you considered?

If notation-core-go does not require/need this, clearly document in README or other public location

Any additional context?

No response

certificate chain validation error message is not returned

The error message for validate certificate is not returned. Here is code.

func isIssuedBy(subject *x509.Certificate, issuer *x509.Certificate) bool {
err := subject.CheckSignatureFrom(issuer)
return err == nil && bytes.Equal(issuer.RawSubject, subject.RawIssuer)
}

The subject.CheckSignatureFrom may return an error and the error message is not returned, which will finally cause an inaccurate error.

Update the branch policies for the repository

After reviewing the branch policies for the repository, it seems that the main and release branches can benefit with more strict push and PR review policies. I would like to propose updating those as follows:
Note: @SteveLasker updated to checkboxes to indicate the current status as some rules were already in place.

  • Follow naming convention release/<release-number> for release branches. Example release/rc.1
  • Use the following rules for main and release/* branches:
    • Require PR before merging
    • Require 3 approvals
    • Dismiss stale PR approvals when new commits are pushed
    • Require review from Code Owners
    • Require status checks to pass before merging
    • Require conversation resolution before merging
    • Require signed commits
    • Do not allow bypass the above settings

Please add your comments and proposals for additional changes to this issue.

vote: tag 1.0.2

Release

This would mean tagging 2bc927b as v1.0.2 to release.

Vote

We need at least 4 approvals from 6 maintainers to release notation-core-go v1.0.2.

Changes

The code changes compared to v1.0.1 include:

  • fix: fix license dependency check workflow by @Two-Hearts in #170
  • build(deps): bump golang.org/x/crypto from 0.14.0 to 0.15.0 by @dependabot in #172
  • doc: update README to align with the new project brand by @FeynmanZhou in #158
  • chore: invalid signing time prompt improvement by @fanndu in #173
  • build(deps): bump golang.org/x/crypto from 0.15.0 to 0.16.0 by @dependabot in #175
  • build(deps): bump actions/setup-go from 4 to 5 by @dependabot in #177
  • build(deps): bump golang.org/x/crypto from 0.16.0 to 0.17.0 by @dependabot in #180
  • build(deps): bump github/codeql-action from 2 to 3 by @dependabot in #179
  • Updated the maintainers and codeowners files by @toddysm in #183
  • build(deps): bump golang.org/x/crypto from 0.17.0 to 0.18.0 by @dependabot in #184

Full Changelog: v1.0.1...2bc927b

Action Requested

Please respond LGTM or REJECT (with reasoning).

Add unit tests to GitHub CI

Make sure every PR has passed unit tests present in the repository. It's ok to copy the existing template from notation-go.

Update the README for the repository

Is your feature request related to a problem?

I propose to update the README.md file for the repository with the following information:

  • link to the overview of the organization
  • purpose of the repository
  • is it in active development or not, is it archived or not, any reasons for that
  • links to relevant documentation (security audits, web site, design documents, etc.)

What solution do you propose?

N/A

What alternatives have you considered?

N/A

Any additional context?

No response

self-signed leaf cert error message not clear

// For self-signed signing certificate (not a CA)
if len(certChain) == 1 {
cert := certChain[0]
if signingTime != nil && (signingTime.Before(cert.NotBefore) || signingTime.After(cert.NotAfter)) {
return fmt.Errorf("certificate with subject %q was not valid at signing time of %s", cert.Subject, signingTime.UTC())
}
if err := cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature); err != nil {
return err
}
return validateLeafCertificate(cert, expectedLeafEku)
}

In line 50 or 53, if it return an error, it had better tell user that there is only one cert and the cert subject is xxxxx with error:xxxx
Also, it may be replaced by isSelfSigned() because it also need to make sure that the issuer and subject are the same.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.