NAV Navigation
HTTP

Hardenize Org API v1.040.0

Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.

Hardenize is a platform for continuous monitoring of network and security configuration. Hardenize supports individual accounts, intended for use by a single person, and organization accounts, which are shared among potentially many individuals. Whereas individual accounts are limited, organization accounts can have access to all Hardenize features. The Organization API, documented here, provides ability to manage and retrieve information from organization accounts.

We are approaching our first stable release, but this specification is still a work in progress and may change without notice.

Overview

Stability and Versioning

This API will soon be declared stable, after which all efforts will be made to ensure background compabitibility. We use semantic version numbers in the form of MAJOR.MINOR.PATCH: the major version number is fixed, the minor version number is incremented every time the API is functionaly changed, and the patch version is changed for documentation updates and bug fixes.

The background compatibility guarantee means that the future API releases won't introduce incompatible changes, but we will continue to make forward-compatible changes. This means that we will add new API endpoints, and that new fields may be added to the objects. To ensure that no breakage takes place, please ensure that your code ignores unknown fields and unknown field values in response objects.

Separately, there are some parts of this API that are not yet considered stable. They are marked as such and can change without notice. The lifecycle of an API extension is roughly that we will release new parts early, polish them in response to feedback, and declare them stable once they're considered mature.

Base Location

This specification shows the API endpoints relative to the API's base location, which is shown below. Before you use the base URL, replace the {org} placeholder with your organization's label:

Request Methods

When it comes to how we use HTTP request methods, we try to follow the spirit of the HTTP specification. We use GET for requests that retrieve information without making any changes on the server. We use POST for requests that modify data. We use DELETE when data is being deleted.

Paths

We use path segments to group API endpoints with common functions, or endpoints that manage the same type of entity (e.g., certificates). Wherever possible, we use plural forms, for example hosts and groups.

We also use path segment parameters (Section 3.3 in the URI RFC) for types of requests that don't alter resource state but request an action to be performed. A nice way to think about this model is that some resources have buttons, and that you are able to push these buttons via actions. You could say that these endpoints are controllers, and they're common in RPC-style APIs.

The first action we implemented was for webhook testing; to test a webhook, you first build a path that identifies a specific webhook, then append a path segment parameter to indicate which action to perform. The complete path then looks like this: /eventHooks/b349dd;test. Although path segments are not very commonly seen in practice, we believe they're very well suited for this particular use case.

HTTP Response Codes

HTTP doesn't provide a full range of useful response codes, but we try to use the status code that makes more sense. In most cases you'll only need to differentiate between 2xx (all good), 4xx (your fault), and 5xx (our fault) responses.

Request limits

We enforce API usage limits in order to preserve the integrity of our systems. For example, it's very easy to deploy a faulty client that sends thousands of requests by mistake, and we wish to defend against situations like that. At this time, we have two mechanisms that can refuse a request. First, we monitor access rate using the token bucket algorithm, and allow approximately one request per second, with an allowance for short-term bursts. Second, we don't allow more than 5 concurrent requests. Both parameters are currently checked on per-organization basis.

Every API response includes a custom X-Request-Allowance header that contains our view of how you're using the API. This is what the output may look like:

r: 57/60 (+1/1s); c: 1/5

The line begins with information about the request rate limits. The first value (57) shows your current request allowance, the second (60) the maximum value. In the brackets, we show that the allowance will be increased (up to the maximum) at the rate of one per second. The second part of the output shows concurrent requests; in this case one of out maximum five.

The best approach would be to limit your client to stay within the allowed limits. Alternatively, if you have a request refused, wait for a full minute, at which point your burst allowance will be fully restored.

These is only our initial approach; we continue to implement what makes sense as we start to learn how our APIs are used.

Resource Identifiers

In this API, every resource has an identifier that uniquely identifies within the parent collection. Wherever it makes sense we try to use natural identifiers, for example hostname for host entities. Where that's not possible we use a synthetic identified and call it id. In this case, treat the identifier as opaque. Despite the fact that the identifier names can vary from entity to entity, they're easy to spot because they're always the first field listed in the documentation.

Data formats

Changelog

v1.040 (19 Jun 2019)

v1.039.0 (13 Jun 2019)

Authentication

Certificates

The APIs in this section allow you to retrieve information about all your certificates, as well as upload your new certificates to us as they become available.

List certificates

Code samples

GET /v1/org/{org}/certs/ HTTP/1.1
Host: api.hardenize.com

GET /certs/

By default, this endpoint returns a list of all your certificates. If you provide one of the optional parameters, only the certificates matching the specified filters will be listed. If you provide multiple parameters, only the certificates matching all the specified filters will be listed.

Parameters

Parameter In Type Description
active query boolean If set, returns only active or inactive certificates
expired query boolean If set, returns only expired or non-expired certificates
expireInDays query integer If set, returns only certificates that have already expired or expire in the specified number of days, according to the effectiveNotAfter timestamp
host query string If set, returns only certificates that are valid for the specified host, either because they contain the exact hostname or because they are wildcards and contain the parent hostname (e.g., a search for blog.example.com will match *.example.com wildcards)
limit query integer If set, returns only up to the specified number of certificates.
newSince query date-time If set, returns only certificates added to the account since the specified date.
spkiSha256 query string If set, returns only certificates whose public key (SPKI) matches the provided hash

Example responses

200 Response

{
  "certs": [
    {
      "sha256": "572908a23e5765a5e64fe06c775075133879ff9eed6e7135ced12e124edeca34\"",
      "tbsSha256": "7d63c93bbbf6d4f7aa492963dccd1ff14b35257b8eca4d912faa0ac1883a92da",
      "subject": "CN=ssl760680.cloudflaressl.com, OU=PositiveSSL Multi-Domain, OU=Domain Control Validated",
      "serial": "d0e65b67fe58f4a5d649cfaa3bb3c2fb",
      "issuer": "CN=COMODO ECC Domain Validation Secure Server CA 2, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB",
      "notBefore": "2019-06-19T08:23:49.954Z",
      "notAfter": "2019-06-19T08:23:49.954Z",
      "effectiveNotAfter": "2019-06-19T08:23:49.954Z",
      "revokedOn": "2019-06-19T08:23:49.954Z",
      "keyAlg": "EC",
      "keyLen": 256,
      "keyStrength": 128,
      "sigAlg": "ECDSAwithSHA256",
      "spkiSha256": "56c17eb4e3d510f7020e142cd36f617b38f93c26c72cc13dfebfbeed3e554382",
      "hosts": [
        "*.hardenize.com"
      ],
      "caPathLen": -1,
      "wildcard": true,
      "selfSigned": false,
      "firstSeen": "2019-06-19T08:23:49.954Z",
      "lastSeen": "2019-06-19T08:23:49.954Z",
      "seenInstalled": true,
      "active": true,
      "precert": false,
      "duplicate": false,
      "managed": true,
      "ownership": "own",
      "matchesOrgHost": true,
      "symantecStatus": "notSymantec",
      "ctRequired": true,
      "ctCompliant": true,
      "ctLogs": [
        {
          "log": "ct.googleapis.com/rocketeer",
          "timestamp": 1533791245857,
          "index": 232455,
          "sources": [
            "cert",
            "log"
          ]
        }
      ],
      "pem": "MIID/TCCA6OgAwIBAgIRANDmW2f+WPSl1knPqjuzwvswCgYIKoZIzj0EAwIwgZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQDEy9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EgMjAeFw0xODAzMDEwMDAwMDBaFw0xODA5MDcyMzU5NTlaMGwxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVsdGktRG9tYWluMSQwIgYDVQQDExtzc2w3NjA2ODAuY2xvdWRmbGFyZXNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjQmXlPI8fSFxAgBabWaZ/llDVh0Qvs6bEDqgu6Ny63HMiW6tXpBpnJs//B2Jysf4vFP2WaxHjD/CwhXyBiylso4IB/TCCAfkwHwYDVR0jBBgwFoAUQAlhZ/C8g3FP3hIILG/U1Ct2PZYwHQYDVR0OBBYEFNsOUClkQN7Qw/9QyXJMVcU+NVA1MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEBAgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMAgGBmeBDAECATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBMi5jcmwwgYgGCCsGAQUFBwEBBHwwejBRBggrBgEFBQcwAoZFaHR0cDovL2NydC5jb21vZG9jYTQuY29tL0NPTU9ET0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQTIuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMEYGA1UdEQQ/MD2CG3NzbDc2MDY4MC5jbG91ZGZsYXJlc3NsLmNvbYIPKi5oYXJkZW5pemUuY29tgg1oYXJkZW5pemUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDebJoLRDhbiDQSDWAb8+C2IkT3sXuL7nH0BYuxHiO32AIgf9YXFRRrzis/p7HVd9X2pkP4CxvriyrLQwpB6s2RFQM=",
      "origin": "ct",
      "originInfo": {
        "net": {
          "host": "aspmx.l.google.com",
          "address": "2a00:1450:400c:c00:0:0:0:1b",
          "port": 25,
          "protocol": "smtp"
        }
      },
      "parentHashes": [
        "25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d",
        "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739"
      ],
      "parentHashesSource": "ct",
      "parentHashesComplete": true
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListCertsResponse

Create certificate

Code samples

POST /v1/org/{org}/certs/ HTTP/1.1
Host: api.hardenize.com
Content-Type: application/x-pem-file

POST /certs/

Use this API endpoint to upload a new certificate to your account. For example, if you've automated certificate generation, we suggest that you also automatically submit all new certificates to Hardenize. That way, when we observe the same certificate via Certificate Transparency, we will know for sure that it belongs to you. We may be able to determine that in any case if we see that the certificate has been installed, but uploading it to us makes this more reliable.

For best results, we recommend that you upload the entire certificate chain received from your CA. That will ensure we also add the required intermediates to your list of certificates. The leaf certificate must be placed first.

Body parameter

-----BEGIN CERTIFICATE-----
MIID/TCCA6OgAwIBAgIRANDmW2f+WPSl1knPqjuzwvswCgYIKoZIzj0EAwIwgZIx
CzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNV
BAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQD
Ey9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0Eg
MjAeFw0xODAzMDEwMDAwMDBaFw0xODA5MDcyMzU5NTlaMGwxITAfBgNVBAsTGERv
bWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVs
dGktRG9tYWluMSQwIgYDVQQDExtzc2w3NjA2ODAuY2xvdWRmbGFyZXNzbC5jb20w
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjQmXlPI8fSFxAgBabWaZ/llDVh0Qv
s6bEDqgu6Ny63HMiW6tXpBpnJs//B2Jysf4vFP2WaxHjD/CwhXyBiylso4IB/TCC
AfkwHwYDVR0jBBgwFoAUQAlhZ/C8g3FP3hIILG/U1Ct2PZYwHQYDVR0OBBYEFNsO
UClkQN7Qw/9QyXJMVcU+NVA1MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAA
MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysG
AQQBsjEBAgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5j
b20vQ1BTMAgGBmeBDAECATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLmNv
bW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZl
ckNBMi5jcmwwgYgGCCsGAQUFBwEBBHwwejBRBggrBgEFBQcwAoZFaHR0cDovL2Ny
dC5jb21vZG9jYTQuY29tL0NPTU9ET0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVT
ZXJ2ZXJDQTIuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQu
Y29tMEYGA1UdEQQ/MD2CG3NzbDc2MDY4MC5jbG91ZGZsYXJlc3NsLmNvbYIPKi5o
YXJkZW5pemUuY29tgg1oYXJkZW5pemUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDe
bJoLRDhbiDQSDWAb8+C2IkT3sXuL7nH0BYuxHiO32AIgf9YXFRRrzis/p7HVd9X2
pkP4CxvriyrLQwpB6s2RFQM=
-----END CERTIFICATE-----

Parameters

Parameter In Type Description
body* body string PEM-encoded certificate or certificate chain. If a chain is provided, the leaf certificate must be placed first.

Example responses

201 Response

{
  "cert": {
    "sha256": "572908a23e5765a5e64fe06c775075133879ff9eed6e7135ced12e124edeca34\"",
    "tbsSha256": "7d63c93bbbf6d4f7aa492963dccd1ff14b35257b8eca4d912faa0ac1883a92da",
    "subject": "CN=ssl760680.cloudflaressl.com, OU=PositiveSSL Multi-Domain, OU=Domain Control Validated",
    "serial": "d0e65b67fe58f4a5d649cfaa3bb3c2fb",
    "issuer": "CN=COMODO ECC Domain Validation Secure Server CA 2, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB",
    "notBefore": "2019-06-19T08:23:49.957Z",
    "notAfter": "2019-06-19T08:23:49.957Z",
    "effectiveNotAfter": "2019-06-19T08:23:49.957Z",
    "revokedOn": "2019-06-19T08:23:49.957Z",
    "keyAlg": "EC",
    "keyLen": 256,
    "keyStrength": 128,
    "sigAlg": "ECDSAwithSHA256",
    "spkiSha256": "56c17eb4e3d510f7020e142cd36f617b38f93c26c72cc13dfebfbeed3e554382",
    "hosts": [
      "*.hardenize.com"
    ],
    "caPathLen": -1,
    "wildcard": true,
    "selfSigned": false,
    "firstSeen": "2019-06-19T08:23:49.957Z",
    "lastSeen": "2019-06-19T08:23:49.957Z",
    "seenInstalled": true,
    "active": true,
    "precert": false,
    "duplicate": false,
    "managed": true,
    "ownership": "own",
    "matchesOrgHost": true,
    "symantecStatus": "notSymantec",
    "ctRequired": true,
    "ctCompliant": true,
    "ctLogs": [
      {
        "log": "ct.googleapis.com/rocketeer",
        "timestamp": 1533791245857,
        "index": 232455,
        "sources": [
          "cert",
          "log"
        ]
      }
    ],
    "pem": "MIID/TCCA6OgAwIBAgIRANDmW2f+WPSl1knPqjuzwvswCgYIKoZIzj0EAwIwgZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQDEy9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EgMjAeFw0xODAzMDEwMDAwMDBaFw0xODA5MDcyMzU5NTlaMGwxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVsdGktRG9tYWluMSQwIgYDVQQDExtzc2w3NjA2ODAuY2xvdWRmbGFyZXNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjQmXlPI8fSFxAgBabWaZ/llDVh0Qvs6bEDqgu6Ny63HMiW6tXpBpnJs//B2Jysf4vFP2WaxHjD/CwhXyBiylso4IB/TCCAfkwHwYDVR0jBBgwFoAUQAlhZ/C8g3FP3hIILG/U1Ct2PZYwHQYDVR0OBBYEFNsOUClkQN7Qw/9QyXJMVcU+NVA1MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEBAgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMAgGBmeBDAECATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBMi5jcmwwgYgGCCsGAQUFBwEBBHwwejBRBggrBgEFBQcwAoZFaHR0cDovL2NydC5jb21vZG9jYTQuY29tL0NPTU9ET0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQTIuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMEYGA1UdEQQ/MD2CG3NzbDc2MDY4MC5jbG91ZGZsYXJlc3NsLmNvbYIPKi5oYXJkZW5pemUuY29tgg1oYXJkZW5pemUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDebJoLRDhbiDQSDWAb8+C2IkT3sXuL7nH0BYuxHiO32AIgf9YXFRRrzis/p7HVd9X2pkP4CxvriyrLQwpB6s2RFQM=",
    "origin": "ct",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "parentHashes": [
      "25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d",
      "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739"
    ],
    "parentHashesSource": "ct",
    "parentHashesComplete": true
  }
}

Responses

Status Meaning Description Schema
201 Created Certificate created. CreateCertResponse
202 Accepted Certificate already exists. CreateCertResponse
400 Bad Request Invalid certificate chain. None

Retrieve certificate

Code samples

GET /v1/org/{org}/certs/{sha256} HTTP/1.1
Host: api.hardenize.com

GET /certs/{sha256}

Returns the certificate with the given SHA256 hash, if available in the account.

Parameters

Parameter In Type Description
sha256* path string none

Example responses

200 Response

{
  "cert": {
    "sha256": "572908a23e5765a5e64fe06c775075133879ff9eed6e7135ced12e124edeca34\"",
    "tbsSha256": "7d63c93bbbf6d4f7aa492963dccd1ff14b35257b8eca4d912faa0ac1883a92da",
    "subject": "CN=ssl760680.cloudflaressl.com, OU=PositiveSSL Multi-Domain, OU=Domain Control Validated",
    "serial": "d0e65b67fe58f4a5d649cfaa3bb3c2fb",
    "issuer": "CN=COMODO ECC Domain Validation Secure Server CA 2, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB",
    "notBefore": "2019-06-19T08:23:49.958Z",
    "notAfter": "2019-06-19T08:23:49.958Z",
    "effectiveNotAfter": "2019-06-19T08:23:49.958Z",
    "revokedOn": "2019-06-19T08:23:49.958Z",
    "keyAlg": "EC",
    "keyLen": 256,
    "keyStrength": 128,
    "sigAlg": "ECDSAwithSHA256",
    "spkiSha256": "56c17eb4e3d510f7020e142cd36f617b38f93c26c72cc13dfebfbeed3e554382",
    "hosts": [
      "*.hardenize.com"
    ],
    "caPathLen": -1,
    "wildcard": true,
    "selfSigned": false,
    "firstSeen": "2019-06-19T08:23:49.958Z",
    "lastSeen": "2019-06-19T08:23:49.958Z",
    "seenInstalled": true,
    "active": true,
    "precert": false,
    "duplicate": false,
    "managed": true,
    "ownership": "own",
    "matchesOrgHost": true,
    "symantecStatus": "notSymantec",
    "ctRequired": true,
    "ctCompliant": true,
    "ctLogs": [
      {
        "log": "ct.googleapis.com/rocketeer",
        "timestamp": 1533791245857,
        "index": 232455,
        "sources": [
          "cert",
          "log"
        ]
      }
    ],
    "pem": "MIID/TCCA6OgAwIBAgIRANDmW2f+WPSl1knPqjuzwvswCgYIKoZIzj0EAwIwgZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQDEy9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EgMjAeFw0xODAzMDEwMDAwMDBaFw0xODA5MDcyMzU5NTlaMGwxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVsdGktRG9tYWluMSQwIgYDVQQDExtzc2w3NjA2ODAuY2xvdWRmbGFyZXNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjQmXlPI8fSFxAgBabWaZ/llDVh0Qvs6bEDqgu6Ny63HMiW6tXpBpnJs//B2Jysf4vFP2WaxHjD/CwhXyBiylso4IB/TCCAfkwHwYDVR0jBBgwFoAUQAlhZ/C8g3FP3hIILG/U1Ct2PZYwHQYDVR0OBBYEFNsOUClkQN7Qw/9QyXJMVcU+NVA1MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEBAgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMAgGBmeBDAECATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBMi5jcmwwgYgGCCsGAQUFBwEBBHwwejBRBggrBgEFBQcwAoZFaHR0cDovL2NydC5jb21vZG9jYTQuY29tL0NPTU9ET0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQTIuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMEYGA1UdEQQ/MD2CG3NzbDc2MDY4MC5jbG91ZGZsYXJlc3NsLmNvbYIPKi5oYXJkZW5pemUuY29tgg1oYXJkZW5pemUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDebJoLRDhbiDQSDWAb8+C2IkT3sXuL7nH0BYuxHiO32AIgf9YXFRRrzis/p7HVd9X2pkP4CxvriyrLQwpB6s2RFQM=",
    "origin": "ct",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "parentHashes": [
      "25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d",
      "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739"
    ],
    "parentHashesSource": "ct",
    "parentHashesComplete": true
  }
}

Responses

Status Meaning Description Schema
200 OK Successfully retrieved certificate GetCertResponse
404 Not Found Certificate not found None

DNS

[Under Development] DNS APIs can be used to synchronize your DNS configuration for Hardenize. Our first supported endpoint enables you to upload your DNS zone files, enabling Hardenize to discover new hosts.

Upload DNS zone

Code samples

POST /v1/org/{org}/dns/zones/?root=example.com HTTP/1.1
Host: api.hardenize.com
Content-Type: text/plain

POST /dns/zones/

Use this endpoint to upload your DNS zone file to Hardenize. The zone file will be parsed to find new hosts, which will then be added to the account.

Body parameter

$ORIGIN example.com.
$TTL 1h
@      IN  SOA   ns.example.com. admin.example.com. ( 2018081601 1d 2h 4w 1h )
@      IN  NS    ns
@      IN  MX    10 mx.example.com.
@      IN  A     192.0.2.1
       IN  AAAA  2001:db8:10::1
ns     IN  A     192.0.2.2
       IN  AAAA  2001:db8:10::2
www    IN  CNAME example.com.
mx     IN  A     192.0.2.3

Parameters

Parameter In Type Description
root* query string The root of the uploaded DNS zone, for example example.com.
body* body string DNS zone file

Responses

Status Meaning Description Schema
204 No Content Zone successfully processed None

Events

We use events to record various things of interest that happen in your account. For example, if we see a certificate that matches one of your domain names in Certificate Transparency (CT) logs, we can take that CT log entry and store it as an event. In this way, you can periodically retrieve the available events and stay up to date. Events are also used as basis for our event hooks, which provide real-time notifications.

We support the following event types:

Event Type Description Event Data
ct.entry One CT log entry matched to the account. The purpose of this event is to enable you to interface directly with the public CT logs while seeing only CT log entries that are relevant to you. One event of this type is generated for every appearance of precertificate and certificate in public CT logs. This usually means that there will be 2-5 events for every precertificate, depending on the certificate validity period. Certificates are also commonly seen in the logs, although that's not guaranteed. In most situations, the pki.cert.new is the more appropriate choice of you only care about new issuance events. We collect all information from your CT log entries even if this event is not enabled; within 24 hours of certificate issuance, the aggregated information will be stored in the appropriate Certificate record. MatchedCtEntry
pki.cert.new New certificate or precertificate added to the account, from any source, including Certificate Transparency, network, or manual upload. The purpose of this event is to enable you to react, in real-time, when a new certificate becomes known. No event is generated for a precertificate for which we already know the certificate. The opposite is not true; if we first see a precertificate and then later its matching certificate, we generate two separate events. If your goal is to monitor unique certificates, you should discard a precertificate for which a certificate is discovered. You can do this using the tbsSha256 field, which will have the same value in the precertificate/certificate combo. This event is generated for own and third-party certificates. If the latter group is not of interest, check the event data fields to discard them. Certificate

Event Hooks

You can use event hooks to have your events pushed to you in real-time. We currently support two delivery mechanisms:

PubSub Event Delivery

PubSub event delivery is a message queue that's implemented on top of Google's PubSub service, which is highly available and stores events for up to 7 days. When we enable this event delivery type, we create one PubSub subscription for the entire account and enable the corresponding hook type. From that point onwards, you can use the API to control exactly which events are delivered to you.

PubSub messages transport event data in the main message body, with the metadata included via the message attributes. PubSub implements at-least-once delivery which means that you may get duplicate events. You can deal with this by designing your processing so that the duplicates don't matter, or by adding a deduplication layer (e.g., based on the unique event identifier).

Webhook Event Delivery

This mechanism submits events to an HTTPS endpoint that you control. This endpoint must be able to accept and process POST requests with event information. The events are transported in the request bodies, using the same format as the events obtained when you pull this information via this API.

When you successfully accept an event we send, you must respond with the 204 No Content status code and no data in the response body. We are particular about the response code because we want to be sure the webhook has been processed correctly. Seeing a 200 response is not really a guarantee of that, as it's common to see web servers configured to always respond with 200 status code, even on processing failure.

Generally speaking, it's always helpful to use meaningful status codes as that will help us understand the type of failure and modify our behavior accordingly. For example:

You should enable keep-alives on your server and use a long timeout value so that we can efficiently send you events in bulk.

It is important that you verify that you are receiving webhooks from us, and not from someone else. There are a couple of ways in which this can be achived. First, you could generate a long random string and embed it in the webhook URL, making it difficult for anyone to just guess the destination you're using. Second, you should check the event metadata to ensure that it matches your expectations. The metadata, which is transported in the request headers, includes a signature based on a per-hook secret.

If a webhook fails, we will continue to attempt delivery over the next 24 hours. Overall, we will attempt delivery of every event to you for about 10 times, backing off exponentially from the first attempt. We may disable webhooks that stay broken for an extended period of time.

Event Hook Metadata

We deliver events along with their associated metadata, as follows:

Event Signatures

We use HMAC-256 to sign a timestamped event body. The X-Hardenize-Signature metadata field will therefore include both the timestamp and the actual signature.

X-Hardenize-Signature: t=1539185809044;
  hmac-sha256=64d386808229f5c84fac665fb6f9376f24efca2971b51713032dca6b83566fd8

To verify the signature, first locate the secret corresponding to the event hoook, using the combination of X-Hardenize-Org and X-Hardenize-EventHookId fields. After that, parse the X-Hardenize-Signature field to extract the timestamp and signature values. To do this, split the value at the semicolon, then extract the key-value pairs. Next, create a new data buffer by appending the timestamp (e.g., 1539185809044), followed by a semicolon (i.e., ;), followed by the verbatim request body. Finally, calculate the HMAC-SHA256 of the data buffer and compare your result with our signature. Please note that our signature is hex-encoded for transport. To do a correct comparison you'll have to either hex-decode it first, or hex-encode your calculation.

If you're worried about replay attacks, you will also need to check that the timestamp doesn't deviate significantly from the time you have. For this to work correctly you need to ensure that you always have the correct time on your server. Additionally, you'll need to be processing the events in near-real time or otherwise account for the processing delay on your end.

If you are unable to validate the event metadata, you must refuse to process the event. If in a webhook, respond with the 400 status code.

Event Collection Best Practices

Even though event hooks are not difficult to set up initially, getting them to work reliably and unattended over an extended period of time will require some effort. Things break. Use event hooks only if there aren't better ways to access the information. For example, if you're interested in the ct.entry and pki.cert.* hooks, consider that we process all the events ourselves, and that information stored in them is always available to you via this API. For example, if you want to keep a copy of all your certificates, it's usually easier to retrieve new and updated certificates daily.

Further, consider these best practices for event hook implementation:

List events

Code samples

GET /v1/org/{org}/events/ HTTP/1.1
Host: api.hardenize.com

GET /events/

Lists events available in the account. By default, all events are listed, with the earliest first. Because there is a forced limit of 100 events per invocation, to iterate over more than 100 events you will need to submit multiple requests, remember the timestamp of the last retrieved event, and use it as the since parameter in the subsequent invocation. If you provide one of the optional parameters, only the events matching the specified filters will be listed. If you provide multiple parameters, only the events matching all the specified filters will be listed.

Parameters

Parameter In Type Description
since query date-time Returns only events that ocurred after the supplied time.
type query string Returns only events that match the supplied type.
limit query integer Limits the number of events in the response. The limit can range between 1 and 100. The default is 100.

Example responses

200 Response

{
  "events": [
    {
      "id": 10001,
      "type": "ct",
      "createdOn": "2019-06-19T08:23:49.959Z",
      "apiVersion": "0.14.0",
      "data": {
        "field": "value"
      }
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListEventsResponse

Get event

Code samples

GET /v1/org/{org}/events/{id} HTTP/1.1
Host: api.hardenize.com

GET /events/{id}

Returns the event with the specified identifier.

Parameters

Parameter In Type Description
id* path integer Event identifier.

Example responses

200 Response

{
  "event": {
    "id": 10001,
    "type": "ct",
    "createdOn": "2019-06-19T08:23:49.960Z",
    "apiVersion": "0.14.0",
    "data": {
      "field": "value"
    }
  }
}

Responses

Status Meaning Description Schema
200 OK OK GetEventResponse
404 Not Found Event doesn't exist None

List event destinations

Code samples

GET /v1/org/{org}/eventDestinations/ HTTP/1.1
Host: api.hardenize.com

GET /eventDestinations/

Lists all managed event destinations. Managed destinations are those that we control, for example PubSub topics.

Example responses

200 Response

{
  "eventDestinations": [
    {
      "destinationId": "pubsub://events/1/1005",
      "type": "pubsub",
      "project": "hz-events-pubsub",
      "topic": "projects/hz-events-pubsub/topics/ep-1-1005",
      "subscription": "ep-1-1005",
      "subscriberCredentials": "{\"type\": \"service_account\", \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\", \"client_id\": \"213792179274932\", \"token_uri\": \"https://oauth2.googleapis.com/token\", \"project_id\": \"hz-events-pubsub\", \"private_key\": \"-----BEGIN PRIVATE KEY-----\\n[REMOVED]\\n-----END PRIVATE KEY-----\\n\", \"client_email\": \"ep-1-1005@hz-events-pubsub.iam.gserviceaccount.com\", \"private_key_id\": \"b407bd79213dc1867aa45ab41e4e955961504f37\", \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/ep-1-1005%40hz-events-pubsub.iam.gserviceaccount.com\", \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\"}"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListEventDestinationsResponse

List event hooks

Code samples

GET /v1/org/{org}/eventHooks/ HTTP/1.1
Host: api.hardenize.com

GET /eventHooks/

Lists event hooks that are configured in the account.

Example responses

200 Response

{
  "eventHooks": [
    {
      "id": "bfc384726b6447a4b70a171de49e466f",
      "hookType": "webhook",
      "eventTypes": [
        "ct.entry"
      ],
      "status": "enabled",
      "destination": "https://hardenize.com/webhooks/receive",
      "secret": "3685c06a966e4d0ea625d0b475719661"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListEventHooksResponse

Create event hook

Code samples

POST /v1/org/{org}/eventHooks/ HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /eventHooks/

Creates a new event hook. Every new event hook starts off as disabled, which means that it's not going to receive events straight away. The expected workflow is to first create an event hook, configure the receiving end, run tests to ensure correct operation, and then finally enable the hook.

Body parameter

{
  "hookType": "webhook",
  "eventTypes": [
    "ct.entry"
  ],
  "status": "enabled",
  "destination": "https://hardenize.com/webhooks/receive"
}

Parameters

Parameter In Type Description
body body CreateEventHookRequest none

Example responses

200 Response

{
  "eventHook": {
    "id": "bfc384726b6447a4b70a171de49e466f",
    "hookType": "webhook",
    "eventTypes": [
      "ct.entry"
    ],
    "status": "enabled",
    "destination": "https://hardenize.com/webhooks/receive",
    "secret": "3685c06a966e4d0ea625d0b475719661"
  }
}

Responses

Status Meaning Description Schema
200 OK Event hook created CreateEventHookResponse
403 Forbidden Insufficient permissions to perform operation None

Delete event hook

Code samples

DELETE /v1/org/{org}/eventHooks/{id} HTTP/1.1
Host: api.hardenize.com

DELETE /eventHooks/{id}

Deletes the event hook with the specified identifier.

Parameters

Parameter In Type Description
id* path string Event hook identifier.

Responses

Status Meaning Description Schema
204 No Content Event hook deleted None
403 Forbidden Insufficient permissions to perform operation None
404 Not Found Event hook not found None

Update event hook

Code samples

POST /v1/org/{org}/eventHooks/{id} HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /eventHooks/{id}

Updates the event hook with the specified identifier.

Body parameter

{
  "eventTypes": [
    "ct.entry"
  ],
  "destination": "https://hardenize.com/webhooks/receive",
  "status": "disabled"
}

Parameters

Parameter In Type Description
id* path string Event hook identifier.
body body UpdateEventHookRequest none

Example responses

200 Response

{
  "eventHook": {
    "id": "bfc384726b6447a4b70a171de49e466f",
    "hookType": "webhook",
    "eventTypes": [
      "ct.entry"
    ],
    "status": "enabled",
    "destination": "https://hardenize.com/webhooks/receive",
    "secret": "3685c06a966e4d0ea625d0b475719661"
  }
}

Responses

Status Meaning Description Schema
200 OK Event hook updated UpdateEventHookResponse
403 Forbidden Insufficient permissions to perform operation None
404 Not Found Event hook not found None

Test event hook

Code samples

POST /v1/org/{org}/eventHooks/{id};test HTTP/1.1
Host: api.hardenize.com

POST /eventHooks/{id};test

Tests the event hook with the specified identifier. By default, we send a test event, but it's possible to request mock events of other types using the eventType parameter. This API endpoint executes synchronously and may take longer than other API calls (especially in case of unresponsive receiving servers).

By default, we submit valid and syntactically events. During the configuration phase, it's useful to test how the receiver behaves with invalid data. We use the invalid parameter for this purpose. Set to any value except none, it instructs the API to intentionally break one element of the submission. In this case, the success criteria also changes. By default, we expect a 204 response, except when we're sending you a broken submission, in which case we expect a 400 in return.

Please note that, when testing deliveries via intermediaries, we're not able to detect processing failures of the final recepient, only of the intermediary. For example, when testing PubSub delivery, this endpoint will return success after successfully publishing to the message queue. Testing with broken events is still useful, but you'll need to detect the failures on the receiving end.

Parameters

Parameter In Type Description
invalid query string Instructs the API to intentionally break one of the elements of the test submission. Default: none
eventType query string Determines the event type that will be sent to the event hook.

Enumerated Values

Parameter Value
invalid none
invalid hookId
invalid org
invalid payload
invalid signature
eventType ct.entry
eventType pki.cert.new
eventType test

Example responses

200 Response

{
  "successful": false,
  "errorMessage": "Expected 202 or 204 status code",
  "durationMillis": 5814,
  "pubsub": {
    "destination": "pubsub://events/1/1005",
    "message": "{\"id\":0,\"createdOn\":\"2018-10-10T15:36:49.044Z\",\"type\":\"test\",\"data\":{\"message\":\"This is a webhook test.\"}}",
    "attributes": {
      "X-Hardenize-EventHookId": "74bf16db59ef4d55aeeb7fe9f7d5171d",
      "X-Hardenize-Org": "demo",
      "X-Hardenize-Signature": "t=1539185809044; hmac-sha256=64d386808229f5c84fac665fb6f9376f24efca2971b51713032dca6b83566fd8"
    },
    "messageId": 260486610038606
  },
  "webook": {
    "request": {
      "method": "POST",
      "url": "https://hardenize.com/webhooks/receive",
      "headers": {
        "Content-Type": "application/json;charset=UTF-8",
        "User-Agent": "Hardenize (https://www.hardenize.com)",
        "X-Hardenize-EventHookId": "74bf16db59ef4d55aeeb7fe9f7d5171d",
        "X-Hardenize-Org": "demo",
        "X-Hardenize-Signature": "t=1539185809044; hmac-sha256=64d386808229f5c84fac665fb6f9376f24efca2971b51713032dca6b83566fd8"
      },
      "body": "{\"id\":0,\"createdOn\":\"2018-10-10T15:36:49.044Z\",\"type\":\"test\",\"data\":{\"message\":\"This is a webhook test.\"}}"
    },
    "response": {
      "statusCode": 302,
      "headers": {
        "Location": "https://hardenize.com/redirection",
        "Cache-Control": "no-cache",
        "Connection": "keep-alive",
        "Content-Type": "text/plain; charset=UTF-8",
        "Date": "Wed, 10 Oct 2018 15:36:54 GMT",
        "Server": "nginx/1.10.3",
        "Transfer-Encoding": "chunked",
        "Vary": "Accept-Encoding"
      },
      "body": "OK"
    }
  }
}

Responses

Status Meaning Description Schema
200 OK Event hook test completed TestEventHookResponse
403 Forbidden Insufficient permissions to perform operation None
404 Not Found Event hook not found None

List event types

Code samples

GET /v1/org/{org}/eventTypes/ HTTP/1.1
Host: api.hardenize.com

GET /eventTypes/

Lists all available event types, showing how they're configured for the account.

Example responses

200 Response

{
  "eventTypes": [
    {
      "name": "ct",
      "available": true,
      "enabled": true
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListEventTypesResponse

Update event type

Code samples

POST /v1/org/{org}/eventTypes/{name} HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /eventTypes/{name}

Updates one event type, changing the enabled property to the specified value. When an event type is enabled, events of that type will be generated and stored in the database. Associated notifications will be dispatched. This operation will fail if the event type is not available in the account.

Body parameter

{
  "enabled": true
}

Parameters

Parameter In Type Description
name* path string Event type name.
body body UpdateEventTypeRequest none

Example responses

200 Response

{
  "eventType": {
    "name": "ct",
    "available": true,
    "enabled": true
  }
}

Responses

Status Meaning Description Schema
200 OK OK UpdateEventTypeResponse
403 Forbidden Not allowed to change status of event that's not available None
404 Not Found Event type doesn't exist None

Groups

[Under Development] We support groups as a general-purpose mechanism for categorization. For example, a host can be assigned zero, one, or more groups.

List groups

Code samples

GET /v1/org/{org}/groups/ HTTP/1.1
Host: api.hardenize.com

GET /groups/

Returns a complete list of all groups used by the organization.

Example responses

200 Response

{
  "groups": [
    {
      "id": "production",
      "name": "Production"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListGroupsResponse

Create group

Code samples

POST /v1/org/{org}/groups/ HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /groups/

Creates a new group. The name you choose should be short (especially if you're planning to assign multiple tags to individual entities) and must not already exist, using case-insensitive comparison.

Body parameter

{
  "id": "production",
  "name": "Production"
}

Parameters

Parameter In Type Description
body body CreateGroupRequest none

Example responses

201 Response

{
  "group": {
    "id": "production",
    "name": "Production"
  }
}

Responses

Status Meaning Description Schema
201 Created Group created CreateGroupResponse
400 Bad Request Invalid parameters None

Delete group

Code samples

DELETE /v1/org/{org}/groups/{id} HTTP/1.1
Host: api.hardenize.com

DELETE /groups/{id}

Deletes a group. By default, only unused groups can be deleted, but you can specify the force parameter to override this behavior.

Parameters

Parameter In Type Description
id* path string The name of the group to delete.
force query boolean If this parameter is provided and set to true, the specified group will be deleted even if it's still in use.

Responses

Status Meaning Description Schema
204 No Content Group deleted None
400 Bad Request Invalid input None
404 Not Found Group not found None

Host Discovery

[Under Development] Host discovery is a feature of Hardenize designed to make it easier for organizations to build their host inventories and keep them up to date. Having a good inventory is key to having good visibility, so we aim to automate the maintenance tasks wherever possible. Where full automation is not possible, we do as much work as we can and present the information for manual review.

There are three principal ways in which new hosts are discovered. The first is the use of authoritative sources. For example, new hosts could be added manually (e.g., from a list of organization's domain names) or could be imported via an integration with existing systems (e.g., authoritative name servers). All accounts are initially populated with data in this way.

Once an account is bootstrapped, our automated discovery features kick in. An important source of information is our monitoring of public infrastructure. We maintain both historical databases and also follow new information that appears on the network. We then inspect these sources to import information that's connected to the account. A good example of this approach is import of new certificates via Certificate Transparency monitoring.

Finally, the third approach is the analysis and import from the data obtained from our own active monitoring of the hosts that are already in an account's host inventory. Because in this case we know that we're dealing with the data that belongs to the account owner, we're able to further refine our understanding and apply heuristics to make even more useful conclusions. For example, as we can your web sites we record and extract useful information from them.

How Host Discovery Works

To support host discovery, we monitor all hosts we come across (as part of both public and private monitoring). When we encounter a relevant host, we import it into the account and add it to the list od discovered hosts.

In some cases (e.g., suffix matching), our discovery is 100% accurate, and then we are able to add thew newly discovered host directly to the inventory. When that's not possible, the new host sits on the discovery list until a decision about it can be made.

If a host is not classified as belonging to the organization, the decision about it stays in the account so that it can be reused in the future.

List host discoveries

Code samples

GET /v1/org/{org}/hostDiscoveries/ HTTP/1.1
Host: api.hardenize.com

GET /hostDiscoveries/

Returns a list of all host discoveries in the account. Optionally, use one of the supported filtering parameters to retrieve only the discoveries that match specific criteria.

Parameters

Parameter In Type Description
resolution query string If set, returns only the host discoveries with this particular resolution set.
discoveredSince query date-time If set, returns only the hosts discoveries that have happened since the supplied date.
origin query string If set, returns only the host discoveries found with this match location.
matchReason query string If set, returns only the host discoveries found with this match reason.
limit query integer If set, returns only up to the specified number of hosts.

Enumerated Values

Parameter Value
resolution pending
resolution own
resolution supplier
resolution unrelated
resolution infringing
resolution phishing
origin hdb
matchReason keyword

Example responses

200 Response

{
  "hostDiscoveries": [
    {
      "id": 11113,
      "autoResolved": false,
      "discoveredHostname": "www.🔥.hardenize.com",
      "discoveredTime": "2019-06-19T08:23:49.965Z",
      "effectiveHostname": "🔥.hardenize.com",
      "origin": "hdb",
      "originInfo": {
        "net": {
          "host": "aspmx.l.google.com",
          "address": "2a00:1450:400c:c00:0:0:0:1b",
          "port": 25,
          "protocol": "smtp"
        }
      },
      "matchReason": "keyword",
      "resolution": "pending",
      "updatedTime": "2019-06-19T08:23:49.965Z"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListHostDiscoveriesResponse

Retrieve host discovery

Code samples

GET /v1/org/{org}/hostDiscoveries/{id} HTTP/1.1
Host: api.hardenize.com

GET /hostDiscoveries/{id}

Returns the specified host discovery.

Parameters

Parameter In Type Description
id* path integer The ID of the host discovery to be fetched.

Example responses

200 Response

{
  "hostDiscovery": {
    "id": 11113,
    "autoResolved": false,
    "discoveredHostname": "www.🔥.hardenize.com",
    "discoveredTime": "2019-06-19T08:23:49.965Z",
    "effectiveHostname": "🔥.hardenize.com",
    "origin": "hdb",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "matchReason": "keyword",
    "resolution": "pending",
    "updatedTime": "2019-06-19T08:23:49.965Z"
  }
}

Responses

Status Meaning Description Schema
200 OK OK GetHostDiscoveryResponse
404 Not Found Host discovery doesn't exist None

Update host discovery

Code samples

POST /v1/org/{org}/hostDiscoveries/{id} HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /hostDiscoveries/{id}

Updates the specified host discovery. Setting the effective hostname is optional, but if a value is provided, it must be the same as the discovered hostname or one of its parents, and must not be a TLD (on the public suffix list). E.g if the discovered hostname is "www.test.example.com", you may set the effective hostname to "test.example.com" or "example.com", but not "com" and not "example.org".

When changing the resolution, the resolution of all other discoveries that have a hostname matching the targetted discoveries effective hostname, are also updated.

When changing the resolution to "own", all affected discoveries are imported into your host inventory.

Body parameter

{
  "resolution": "pending",
  "effectiveHostname": "🔥.hardenize.com"
}

Parameters

Parameter In Type Description
id* path integer The ID of the host discovery to be updated.
body body UpdateHostDiscoveryRequest none

Example responses

200 Response

{
  "hostDiscovery": {
    "id": 11113,
    "autoResolved": false,
    "discoveredHostname": "www.🔥.hardenize.com",
    "discoveredTime": "2019-06-19T08:23:49.966Z",
    "effectiveHostname": "🔥.hardenize.com",
    "origin": "hdb",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "matchReason": "keyword",
    "resolution": "pending",
    "updatedTime": "2019-06-19T08:23:49.966Z"
  }
}

Responses

Status Meaning Description Schema
200 OK OK UpdateHostDiscoveryResponse
404 Not Found Host discovery doesn't exist None

Host Discovery Keywords

[Under Development] Hardenize supports discovery of new hosts based on keyword matching. To support this type of discovery we maintain databases of public hostnames and domain names. When a keyword is added to the account, we schedule a scan of this database for any hostnames which match it.

Our keyword matching discovery is different from subdomain matching because it looks for a match anywhere in the hostname. Additionally, we implement a fuzzy matching algorithm that's designed to defeat obfuscations that attempt to construct hostnames that appear to be something else. Examples of fuzzy matching include simple character substitition (e.g., tw1tter) and the use of Unicode characters that can be confused for one another (also known as homoglyphs or homographs).

After adding a keyword to your account, we wait until approximately 3am UTC and then scan our historical database of hostnames, for all matches. We then continue to scan for new hostnames that match the keyword every 5 minutes onwards. What this means is, after adding a keyword to your account, you wont see any matches until at least 3am, but after that, you'll get fairly immediate updates.

Using Keyword Discovery

To use keyword discovery, specify one or more keywords for us to use. We will find all the matching hostnames and store them along with all other discovered hostnames for you to review.

Because this discovery mechanism can trigger on a very large number of hostnames, every account is configured with a total limit of hostnames that can be discovered via keyword matching. If this limit is reached, keyword discovery will be suspended and you will be notified. You should at that point review and update the noisy keywords, remove the unwanted matches, and reactivate the matching. The default limit is 10,000.

Keyword discovery is not available on all account tiers. Before you attempt to use this feature, check if your account supports it.

List host discovery keywords

Code samples

GET /v1/org/{org}/hostDiscoveryKeywords/ HTTP/1.1
Host: api.hardenize.com

GET /hostDiscoveryKeywords/

Returns a list of all host discovery keywords in the account.

Example responses

200 Response

{
  "hostDiscoveryKeywords": [
    {
      "keyword": "hardenize"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListHostDiscoveryKeywordsResponse

Create host discovery keyword

Code samples

POST /v1/org/{org}/hostDiscoveryKeywords/ HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /hostDiscoveryKeywords/

Creates a new keyword to be used for host discovery. It's important to choose a good keyword that will not produce many false positives. For example, if you specified the word com, we would match on millions of hostnames.

As a safety measure, each keyword submitted to this endpoint is tested prior to acceptance. For the test, we count how many hostnames there are that contain the keyword. This test is simpler than our usual matching, but it enables us to estimate how many matches there will be. By default, a keyword that results in 1,000 or more matches will be rejected.

Keyword matching never returns any hostnames that are considered to belong to the account organization. The exclusion happens automatically because those hostnames should have already been added to the account via suffix matching.

Body parameter

{
  "keyword": "hardenize"
}

Parameters

Parameter In Type Description
body body HostDiscoveryKeyword none

Example responses

200 Response

{
  "hostDiscoveryKeyword": {
    "keyword": "hardenize"
  }
}

Responses

Status Meaning Description Schema
200 OK OK CreateHostDiscoveryKeywordResponse
400 Bad Request Keyword creation rejected. It would create too many matches None

Retrieve host discovery keyword

Code samples

GET /v1/org/{org}/hostDiscoveryKeywords/{keyword} HTTP/1.1
Host: api.hardenize.com

GET /hostDiscoveryKeywords/{keyword}

Retrieves a host discovery keyword.

Parameters

Parameter In Type Description
keyword* path string The name of the keyword to fetch.

Example responses

200 Response

{
  "hostDiscoveryKeyword": {
    "keyword": "hardenize"
  }
}

Responses

Status Meaning Description Schema
200 OK OK GetHostDiscoveryKeywordResponse
404 Not Found Keyword not found None

Delete host discovery keyword

Code samples

DELETE /v1/org/{org}/hostDiscoveryKeywords/{keyword} HTTP/1.1
Host: api.hardenize.com

DELETE /hostDiscoveryKeywords/{keyword}

Deletes a host discovery keyword.

Parameters

Parameter In Type Description
keyword* path string The name of the keyword to delete.

Responses

Status Meaning Description Schema
204 No Content Keyword deleted None
404 Not Found Keyword not found None

Hosts

Host management, which provides abilities to create and delete your hosts, as well as configure how they're monitored. You are also able to manage how hosts are discovered in this section.

In this section and elsewhere in the API, wherever we accept hostnames, we validate them and perform canonicalization: we convert them to lowercase, and strip the trailing dot if present. This means that the hosts we keep in the database will potentially be different at the character level from the hosts you input. However, they will be semantically the same.

List hosts

Code samples

GET /v1/org/{org}/hosts/ HTTP/1.1
Host: api.hardenize.com

GET /hosts/

Returns a list of all hosts in the account. If you provide one of the optional parameters, only the hosts matching the specified filters will be listed. If you provide multiple parameters, only the certificates matching all the specified filters will be listed.

Parameters

Parameter In Type Description
group query string If set, returns only the hosts that belong to the specified group.
hostname query string If set, returns only the hosts whose names match the parameter. One or more hosts may be returned, depending on whether subdomains are being included.
limit query integer If set, returns only up to the specified number of hosts.
origin query string If set, returns only the hosts whose origins match the parameter.
status query string If set, returns only the hosts whose statuses match the parameter.
subdomains query boolean If set, extends the host matching to include all subdomains of the specified name. Default: true.

Enumerated Values

Parameter Value
origin cert
origin ct
origin hdb
origin manual
status monitored
status idle
status archived

Example responses

200 Response

{
  "hosts": {
    "hostname": "🔥.hardenize.com",
    "punyHostname": "xn--4v8h.hardenize.com",
    "createdOn": "2019-06-19T08:23:49.967Z",
    "status": "archived",
    "origin": "hdb",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "nx": true,
    "nxTime": "2019-06-19T08:23:49.967Z",
    "lastAssessmentTime": "2019-06-19T08:23:49.967Z",
    "assessmentError": "Host not found",
    "lastAssessmentAttemptTime": "2019-06-19T08:23:49.967Z"
  }
}

Responses

Status Meaning Description Schema
200 OK OK ListHostsResponse
400 Bad Request Invalid parameters provided None

Create hosts

Code samples

POST /v1/org/{org}/hosts/ HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /hosts/

Adds one or more hosts to the account. No errors will be reported if the list includes one or more hosts that already exist. In that situation, the existing hosts will be treated in the same way as the new hosts when it comes to their status and group membership. New groups are added if required, but existing group memberships won't be affected. If the status field is not provided then the initial host status will be automatically decided following the account rules for newly discovered hosts.

Body parameter

{
  "hostnames": [
    "example.com"
  ],
  "status": "monitored",
  "groups": [
    "production"
  ]
}

Parameters

Parameter In Type Description
body body CreateHostsRequest Names of the hosts that are to be created, along with their initial status.

Responses

Status Meaning Description Schema
204 No Content Hosts added to the account None
400 Bad Request Invalid parameters provided None

Delete hosts

Code samples

DELETE /v1/org/{org}/hosts/ HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

DELETE /hosts/

Deletes one or more hosts from the account. This operation will delete all the data exclusively associated with the specified hosts, as well as all their history. The subdomains are also deleted if the subdomains option is enabled. Use the delete operation only on the hosts that have been added to your account by mistake, in other words on the hosts that don't belong to you. For hosts that do belong to you but you wish to ignore, set their status to archived. Role: Admin.

Body parameter

{
  "hostnames": [
    "example.com"
  ],
  "subdomains": true,
  "preview": true
}

Parameters

Parameter In Type Description
body body DeleteHostsRequest none

Example responses

200 Response

{
  "hostnames": [
    "example.com"
  ],
  "preview": true
}

Responses

Status Meaning Description Schema
200 OK Hosts successfully deleted DeleteHostsResponse
400 Bad Request Invalid parameters provided None

Update hosts

Code samples

POST /v1/org/{org}/hosts/*/ HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /hosts/*/

Updates one or more hosts that are already stored in the account.

Body parameter

{
  "hostnames": [
    "example.com"
  ],
  "preview": true,
  "subdomains": true,
  "changes": {
    "status": "monitored",
    "groupOp": "add",
    "groups": [
      "staging",
      "development"
    ]
  }
}

Parameters

Parameter In Type Description
body body UpdateHostsRequest none

Example responses

200 Response

{
  "hostnames": [
    "example.com"
  ],
  "preview": true
}

Responses

Status Meaning Description Schema
200 OK Hosts successfully updated UpdateHostsResponse
400 Bad Request Invalid parameters provided None

Retrieve host

Code samples

GET /v1/org/{org}/hosts/{hostname} HTTP/1.1
Host: api.hardenize.com

GET /hosts/{hostname}

Returns the host with the specified name.

Parameters

Parameter In Type Description
hostname* path string The name of the host whose data you wish to retrieve.

Example responses

200 Response

{
  "host": [
    {
      "hostname": "🔥.hardenize.com",
      "punyHostname": "xn--4v8h.hardenize.com",
      "createdOn": "2019-06-19T08:23:49.968Z",
      "status": "archived",
      "origin": "hdb",
      "originInfo": {
        "net": {
          "host": "aspmx.l.google.com",
          "address": "2a00:1450:400c:c00:0:0:0:1b",
          "port": 25,
          "protocol": "smtp"
        }
      },
      "nx": true,
      "nxTime": "2019-06-19T08:23:49.969Z",
      "lastAssessmentTime": "2019-06-19T08:23:49.969Z",
      "assessmentError": "Host not found",
      "lastAssessmentAttemptTime": "2019-06-19T08:23:49.969Z"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListHostResponse
400 Bad Request Invalid parameters provided None
404 Not Found Host not found None

Reports

In the Report section of the API we provide summaries of the reports done for your monitored hosts. This is the same information that's available in the web application under the Sites navigation. This section of the API is transient and will be replaced with a more comprehensive implementation in the near future. That's why we have the zero ("0") in the endpoint path.

List reports

Code samples

GET /v1/org/{org}/reports0/ HTTP/1.1
Host: api.hardenize.com

GET /reports0/

Returns all available reports. If you provide one of the optional parameters, only the reports matching the specified filters will be listed. If you provide multiple parameters, only the reports matching all the specified filters will be listed.

Parameters

Parameter In Type Description
format query string The name of the host whose report summary you wish to retrieve. Default: json.
name query string The name of the host whose report summary you wish to retrieve.
subdomains query boolean If set, extends the host matching to include all subdomains of the specified name. Default: false.
group query string If set, returns only the summaries for hosts that belong to the specified group.

Enumerated Values

Parameter Value
format csv
format json

Example responses

200 Response

{
  "reports": [
    {
      "hostname": "example.com",
      "status": "completed",
      "reportTime": "2018-10-10T15:36:49.044Z",
      "hasDnssec": true,
      "hasSmtp": true,
      "hasSmtpTls": true,
      "hasSmtpDane": true,
      "hasSpf": true,
      "hasDmarc": true,
      "hasHttp": true,
      "hasHttps": true,
      "hasHttpsDane": true,
      "hasHttpRedirection": true,
      "hasHsts": true,
      "hasHstsPreloaded": true,
      "nameServers": "string",
      "dnssec": "string",
      "emailTls": "string",
      "emailDane": "string",
      "spf": "string",
      "dmarc": "string",
      "wwwTls": "string",
      "wwwDane": "string",
      "hsts": "string",
      "hpkp": "string",
      "cookies": "string",
      "mixedContent": "string",
      "securityHeaders": "string",
      "csp": "string"
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListReports0Response

Organizations

Depending on the type of subscription, organization accounts can be configured to allow creation of nested organizations. These suborganizations are designed to be fully independent, although it's possible to retain some level of control over them via the API.

New suborganizations support the same API endpoints, although the capabilities will typically be different to that of the master account. To access a suborganization via this API, first use the master account to create a new set of API credentials. Subsequently, use the new credentials to access the suborganization directly. Do note that the suborganization identifiers exposed by this API are relative to that of the parent account. When accessing suborganization APIs directly you need to use the complete account identified, which will be in the form of parent.child. Attempting to use an incorrect identified will result in a 404 response.

List Organizations

Code samples

GET /v1/org/{org}/suborgs/ HTTP/1.1
Host: api.hardenize.com

GET /suborgs/

Returns a complete list of all organizations nested under this account.

Example responses

200 Response

{
  "orgs": [
    {
      "id": "hardenize",
      "name": "Hardenize",
      "status": "active",
      "commercialStatus": "internal",
      "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
      "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
      "hostsAutoimportSubdomains": true,
      "limitTotalHostsHard": -1
    }
  ]
}

Responses

Status Meaning Description Schema
200 OK OK ListOrgsResponse
403 Forbidden Account doesn't support suborganizations None

Create Organization

Code samples

POST /v1/org/{org}/suborgs/ HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /suborgs/

Creates a new suborganization under this account. If successful, this endpoint returns full information about the newly-created organization.

Body parameter

{
  "id": "hardenize",
  "name": "Hardenize",
  "status": "active",
  "commercialStatus": "internal",
  "generateApiCredentials": true,
  "hostsAutoimportSubdomains": true,
  "limitTotalHostsHard": -1
}

Parameters

Parameter In Type Description
body body CreateOrgRequest none

Example responses

200 Response

{
  "org": {
    "id": "hardenize",
    "name": "Hardenize",
    "status": "active",
    "commercialStatus": "internal",
    "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
    "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
    "hostsAutoimportSubdomains": true,
    "limitTotalHostsHard": -1
  }
}

Responses

Status Meaning Description Schema
200 OK Organization created CreateOrgResponse
400 Bad Request Invalid parameters or organization with the supplied id or name already exists. None
403 Forbidden Account doesn't support suborganizations None

Retrieve Organization

Code samples

GET /v1/org/{org}/suborgs/{id} HTTP/1.1
Host: api.hardenize.com

GET /suborgs/{id}

Returns the specified nested organization.

Parameters

Parameter In Type Description
id* path string Organization identifier.

Example responses

200 Response

{
  "suborg": {
    "id": "hardenize",
    "name": "Hardenize",
    "status": "active",
    "commercialStatus": "internal",
    "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
    "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
    "hostsAutoimportSubdomains": true,
    "limitTotalHostsHard": -1
  }
}

Responses

Status Meaning Description Schema
200 OK OK GetOrgResponse
403 Forbidden Account doesn't support suborganizations None
404 Not Found Organization doesn't exist None

Delete Organization

Code samples

DELETE /v1/org/{org}/suborgs/{id} HTTP/1.1
Host: api.hardenize.com

DELETE /suborgs/{id}

Permanently deletes one nested organization. Because this operation is irreversible and thus quite dangerous, this endpoint is typically disabled by default, and may be enabled on sandbox accounts only. The recommended way to delete organizations is to set the status to deleted.

Parameters

Parameter In Type Description
id* path string Organization identifier.

Responses

Status Meaning Description Schema
204 No Content Organization deleted None
403 Forbidden Account doesn't support suborganizations, or the delete operation not permitted None
404 Not Found Organization doesn't exist None

Update Organization

Code samples

POST /v1/org/{org}/suborgs/{id} HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /suborgs/{id}

Updates the desired nested organization.

Body parameter

{
  "status": "active",
  "commercialStatus": "internal",
  "generateApiCredentials": true,
  "hostsAutoimportSubdomains": true,
  "limitTotalHostsHard": -1
}

Parameters

Parameter In Type Description
id* path string Organization identifier.
body body UpdateOrgRequest none

Example responses

200 Response

{
  "suborg": {
    "id": "hardenize",
    "name": "Hardenize",
    "status": "active",
    "commercialStatus": "internal",
    "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
    "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
    "hostsAutoimportSubdomains": true,
    "limitTotalHostsHard": -1
  }
}

Responses

Status Meaning Description Schema
200 OK OK UpdateOrgResponse
403 Forbidden Account doesn't support suborganizations None
404 Not Found Organization doesn't exist None

Users

[Under Development] For managing organization users.

Update User

Code samples

POST /v1/org/{org}/users/{id} HTTP/1.1
Host: api.hardenize.com
Content-Type: application/json

POST /users/{id}

Updates the desired user.

Body parameter

{
  "deleteMfa": true
}

Parameters

Parameter In Type Description
id* path integer User identifier.
body body UpdateUserRequest none

Responses

Status Meaning Description Schema
204 No Content User updated None
400 Bad Request Invalid parameters or user with the supplied id does not have an email address on one of the organization corporate domains. None
403 Forbidden You don't have permission to disable MFA. This will happen if you used session auth instead of an API token, and your user is not an org admin. None
404 Not Found User with given id doesn't exist within organization None

Schemas

Certificate

{
  "sha256": "572908a23e5765a5e64fe06c775075133879ff9eed6e7135ced12e124edeca34\"",
  "tbsSha256": "7d63c93bbbf6d4f7aa492963dccd1ff14b35257b8eca4d912faa0ac1883a92da",
  "subject": "CN=ssl760680.cloudflaressl.com, OU=PositiveSSL Multi-Domain, OU=Domain Control Validated",
  "serial": "d0e65b67fe58f4a5d649cfaa3bb3c2fb",
  "issuer": "CN=COMODO ECC Domain Validation Secure Server CA 2, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB",
  "notBefore": "2019-06-19T08:23:49.972Z",
  "notAfter": "2019-06-19T08:23:49.972Z",
  "effectiveNotAfter": "2019-06-19T08:23:49.972Z",
  "revokedOn": "2019-06-19T08:23:49.972Z",
  "keyAlg": "EC",
  "keyLen": 256,
  "keyStrength": 128,
  "sigAlg": "ECDSAwithSHA256",
  "spkiSha256": "56c17eb4e3d510f7020e142cd36f617b38f93c26c72cc13dfebfbeed3e554382",
  "hosts": [
    "*.hardenize.com"
  ],
  "caPathLen": -1,
  "wildcard": true,
  "selfSigned": false,
  "firstSeen": "2019-06-19T08:23:49.972Z",
  "lastSeen": "2019-06-19T08:23:49.972Z",
  "seenInstalled": true,
  "active": true,
  "precert": false,
  "duplicate": false,
  "managed": true,
  "ownership": "own",
  "matchesOrgHost": true,
  "symantecStatus": "notSymantec",
  "ctRequired": true,
  "ctCompliant": true,
  "ctLogs": [
    {
      "log": "ct.googleapis.com/rocketeer",
      "timestamp": 1533791245857,
      "index": 232455,
      "sources": [
        "cert",
        "log"
      ]
    }
  ],
  "pem": "MIID/TCCA6OgAwIBAgIRANDmW2f+WPSl1knPqjuzwvswCgYIKoZIzj0EAwIwgZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQDEy9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EgMjAeFw0xODAzMDEwMDAwMDBaFw0xODA5MDcyMzU5NTlaMGwxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVsdGktRG9tYWluMSQwIgYDVQQDExtzc2w3NjA2ODAuY2xvdWRmbGFyZXNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjQmXlPI8fSFxAgBabWaZ/llDVh0Qvs6bEDqgu6Ny63HMiW6tXpBpnJs//B2Jysf4vFP2WaxHjD/CwhXyBiylso4IB/TCCAfkwHwYDVR0jBBgwFoAUQAlhZ/C8g3FP3hIILG/U1Ct2PZYwHQYDVR0OBBYEFNsOUClkQN7Qw/9QyXJMVcU+NVA1MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEBAgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMAgGBmeBDAECATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBMi5jcmwwgYgGCCsGAQUFBwEBBHwwejBRBggrBgEFBQcwAoZFaHR0cDovL2NydC5jb21vZG9jYTQuY29tL0NPTU9ET0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQTIuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMEYGA1UdEQQ/MD2CG3NzbDc2MDY4MC5jbG91ZGZsYXJlc3NsLmNvbYIPKi5oYXJkZW5pemUuY29tgg1oYXJkZW5pemUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDebJoLRDhbiDQSDWAb8+C2IkT3sXuL7nH0BYuxHiO32AIgf9YXFRRrzis/p7HVd9X2pkP4CxvriyrLQwpB6s2RFQM=",
  "origin": "ct",
  "originInfo": {
    "net": {
      "host": "aspmx.l.google.com",
      "address": "2a00:1450:400c:c00:0:0:0:1b",
      "port": 25,
      "protocol": "smtp"
    }
  },
  "parentHashes": [
    "25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d",
    "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739"
  ],
  "parentHashesSource": "ct",
  "parentHashesComplete": true
}

Properties

Name Type Description
sha256* string Hex-encoded SHA256 hash of the certificate in DER format.
tbsSha256 string Hex-encoded SHA256 hash of the TBSCertificate structure. A certificate and its precertificate will have the same tbsSha256 value.
subject* string Subject distinguished name.
serial* string Hex-encoded serial number.
issuer* string Issuer distinguished name.
notBefore* date-time ISO 8601 timestamp.
notAfter* date-time ISO 8601 timestamp.
effectiveNotAfter* date-time ISO 8601 timestamp. This fields contains the time after which the certificate cannot be used in practice. For example, certificates issued from the old Symantec PKI infrastructure have been deprecated and can no longer be used for web sites, even though they are still technically valid. Depending on the deprecation phase, Symantec certificates will have the effective dates of March 1, 2018 (phase one) or September 1, 2018 (phase 2).
revokedOn* date-time Revocation timestamp, if available.
keyAlg* string Private key algorithm, for example RSA or EC.
keyLen* integer Private key length, for example 256 for an ECDSA key or 2048 for an RSA key.
keyStrength* integer Estimated private key strength in symmetric bits. For example, a 256-bit ECDSA key is thought to provide 128 bits of security, whereas a 2048-bit RSA key provides about 112.
sigAlg* string Certificate signature algorithm.
spkiSha256* string Hex-encoded SHA256 of the certificate's SPKI component.
hosts* [string] All hosts specified in the certificate's SAN extension, as Unicode. This list includes both hostnames and IP addresses. Wildcard hostnames will be on the list if they are in the certificate.
caPathLen* integer Indicates if this is a CA certificate. Leaf certificates will have -1 in this field, indicating that they cannot issue further certificates. CA certificates will have 0 or a positive number. CA certificates without path length limit will have 2,147,483,647.
wildcard* boolean Set to true if at least one of the allowed hosts is a wildcard.
selfSigned* boolean Set to true if this is a self-signed certificate.
firstSeen* date-time The first time this certificate was seen, which could be a variety of sources for example, CT, manual upload, or installed on a server.
lastSeen* date-time The last time this certificate was seen installed on a server.
seenInstalled* boolean Indicates if this certificate has been seen installed on a server.
active* boolean Indicates if this certificate has been seen installed recently.
precert* boolean Indicates if the returned certificate is, in fact, a precertificate.
duplicate* boolean Set to true on a precertificate for which the certificate is known.
managed* boolean Indicates if this certificate is managed, i.e. provided by a third-party service that will also automatically renew the certificate when it becomes due.
ownership* string Indicates if this certificate belongs to the organisation, which means that it is served from one of the organization's properties. Do note that, in the case of certificate name mismatch, someone else's certificate may be considered as own. In that case, the matchesOrgHost field will be set to false.
matchesOrgHost* boolean Indicates if at least one of the host listed in the certificates matches a hosts that belongs to the organisation.
symantecStatus string Indicates if this certificate was issued from Symantec's PKI infrastructure. This field is not set when it's not necessary, as absence of value indicates that the certificate did not come from Symantec. This field is also never set on CA intermediates and roots.
ctRequired boolean Indicates whether certificate is required to be logged to CT for use on public sites. This is a requirement for all certificates issued from May 2018 onwards, as well for some earlier Symantec certificates.
ctCompliant boolean Indicates whether certificate embeds sufficient SCTs to satisfy CT compliance.
ctLogs* [CertCtLog] none
pem* string Base64-encoded certificate in DER format.
origin* string Indication of where this certificate was obtained from. This field will contain ct if the certificate was found in Certificate Transparency logs, manual if the certificate was provided to us (e.g., if it was uploaded via the API) and net if the certificate was observed on the network.
originInfo OriginInfo Further information about the certificate origin. For example, if the origin is network, then this field will contain the exact network location.
parentHashes [string] Contains the SHA256 fingerprints of parent certificates, if they are known. We currently populate this field only using the information obtained from CT log entries.
parentHashesSource string Indicates the source of the parent hashes provided in the parentHashes field. If the field contains ct, that means that the parent hashes are exactly as seen in CT. CT entries are not guaranteed to include the root; if we're able to find the right root, we'll use the value ctPlusRoot to indicate that the bulk of the chain is from CT, but that we appended a root to it. The value hardenize is reserved for future use, when we implement path building to identify the hashes for certificates only seen online (and not in CT).
parentHashesComplete boolean True if the parent hashes are available and form a complete chain, false if parent hashes are available but the chain is not complete. This field is not available when parent hashes are not available.

Enumerated Values

Property Value
sigAlg RSAwithMD2
sigAlg RSAwithMD5
sigAlg RSAwithSHA1
sigAlg RSAwithSHA256
sigAlg RSAwithSHA384
sigAlg RSAwithSHA512
sigAlg RSAPSS
sigAlg DSAwithSHA1
sigAlg DSAwithSHA256
sigAlg ECDSAwithSHA1
sigAlg ECDSAwithSHA256
sigAlg ECDSAwithSHA384
sigAlg ECDSAwithSHA512
ownership own
ownership thirdParty
symantecStatus phaseOneAffected
symantecStatus phaseOneNotAffected
symantecStatus phaseTwoAffected
symantecStatus phaseTwoNotAffected
symantecStatus symantecExcluded
origin ct
origin manual
origin net
parentHashesSource ct
parentHashesSource ctPlusRoot
parentHashesSource hardenize

CertCtLog

{
  "log": "ct.googleapis.com/rocketeer",
  "timestamp": 1533791245857,
  "index": 232455,
  "sources": [
    "cert",
    "log"
  ]
}

Properties

Name Type Description
log* string CT log URL, with the scheme omitted.
timestamp* integer(int64) Milliseconds since January 1, 1970, excluding leap seconds, per CT RFC.
index integer(int64) This certificate's index in the referenced CT log.
sources* array Hardenize collects CT information from multiple sources. This set indicates all the places where we've collected the information we have on a certificate.

Enumerated Values

Property Value
sources cert
sources log
sources ocsp
sources tls

CreateHostsRequest

{
  "hostnames": [
    "example.com"
  ],
  "status": "monitored",
  "groups": [
    "production"
  ]
}

Properties

Name Type Description
hostnames* [string] List of hosts to create. Each host in this array must be a valid registrable domain (according to the Public Suffix List) or a subdomain of a registrable domain.
status string Desired host status. If the status is not specified, the initial status is determined based on the account's default status for new hosts as well as the status of parent hosts (depending on the configuration).
groups [string] List of groups to which the new hosts should be added. If the account is configured to inherit group membership from parent hosts, those groups are added in addition to the ones explicitly specified here.

Enumerated Values

Property Value
status monitored
status idle
status archived

CreateHostDiscoveryKeywordRequest

{
  "keyword": "hardenize"
}

Properties

None

CreateHostDiscoveryKeywordResponse

{
  "hostDiscoveryKeyword": {
    "keyword": "hardenize"
  }
}

Properties

Name Type Description
hostDiscoveryKeyword HostDiscoveryKeyword A keyword used for host discovery.

CreateCertResponse

{
  "cert": {
    "sha256": "572908a23e5765a5e64fe06c775075133879ff9eed6e7135ced12e124edeca34\"",
    "tbsSha256": "7d63c93bbbf6d4f7aa492963dccd1ff14b35257b8eca4d912faa0ac1883a92da",
    "subject": "CN=ssl760680.cloudflaressl.com, OU=PositiveSSL Multi-Domain, OU=Domain Control Validated",
    "serial": "d0e65b67fe58f4a5d649cfaa3bb3c2fb",
    "issuer": "CN=COMODO ECC Domain Validation Secure Server CA 2, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB",
    "notBefore": "2019-06-19T08:23:49.975Z",
    "notAfter": "2019-06-19T08:23:49.975Z",
    "effectiveNotAfter": "2019-06-19T08:23:49.975Z",
    "revokedOn": "2019-06-19T08:23:49.975Z",
    "keyAlg": "EC",
    "keyLen": 256,
    "keyStrength": 128,
    "sigAlg": "ECDSAwithSHA256",
    "spkiSha256": "56c17eb4e3d510f7020e142cd36f617b38f93c26c72cc13dfebfbeed3e554382",
    "hosts": [
      "*.hardenize.com"
    ],
    "caPathLen": -1,
    "wildcard": true,
    "selfSigned": false,
    "firstSeen": "2019-06-19T08:23:49.975Z",
    "lastSeen": "2019-06-19T08:23:49.975Z",
    "seenInstalled": true,
    "active": true,
    "precert": false,
    "duplicate": false,
    "managed": true,
    "ownership": "own",
    "matchesOrgHost": true,
    "symantecStatus": "notSymantec",
    "ctRequired": true,
    "ctCompliant": true,
    "ctLogs": [
      {
        "log": "ct.googleapis.com/rocketeer",
        "timestamp": 1533791245857,
        "index": 232455,
        "sources": [
          "cert",
          "log"
        ]
      }
    ],
    "pem": "MIID/TCCA6OgAwIBAgIRANDmW2f+WPSl1knPqjuzwvswCgYIKoZIzj0EAwIwgZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQDEy9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EgMjAeFw0xODAzMDEwMDAwMDBaFw0xODA5MDcyMzU5NTlaMGwxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVsdGktRG9tYWluMSQwIgYDVQQDExtzc2w3NjA2ODAuY2xvdWRmbGFyZXNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjQmXlPI8fSFxAgBabWaZ/llDVh0Qvs6bEDqgu6Ny63HMiW6tXpBpnJs//B2Jysf4vFP2WaxHjD/CwhXyBiylso4IB/TCCAfkwHwYDVR0jBBgwFoAUQAlhZ/C8g3FP3hIILG/U1Ct2PZYwHQYDVR0OBBYEFNsOUClkQN7Qw/9QyXJMVcU+NVA1MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEBAgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMAgGBmeBDAECATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBMi5jcmwwgYgGCCsGAQUFBwEBBHwwejBRBggrBgEFBQcwAoZFaHR0cDovL2NydC5jb21vZG9jYTQuY29tL0NPTU9ET0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQTIuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMEYGA1UdEQQ/MD2CG3NzbDc2MDY4MC5jbG91ZGZsYXJlc3NsLmNvbYIPKi5oYXJkZW5pemUuY29tgg1oYXJkZW5pemUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDebJoLRDhbiDQSDWAb8+C2IkT3sXuL7nH0BYuxHiO32AIgf9YXFRRrzis/p7HVd9X2pkP4CxvriyrLQwpB6s2RFQM=",
    "origin": "ct",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "parentHashes": [
      "25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d",
      "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739"
    ],
    "parentHashesSource": "ct",
    "parentHashesComplete": true
  }
}

Properties

Name Type Description
cert Certificate none

CreateEventHookRequest

{
  "hookType": "webhook",
  "eventTypes": [
    "ct.entry"
  ],
  "status": "enabled",
  "destination": "https://hardenize.com/webhooks/receive"
}

Properties

Name Type Description
hookType* string Desired event hook type.
eventTypes* [string] A list of event types to send to this event hook.
status string Initial status for this hook. Default: disabled.
destination* string Event hook destination; for webhooks, this must be an HTTPS URL. For deliveries via PubSub, you must supply here a valid destination obtained via the List Event Destinations API endpoint.

Enumerated Values

Property Value
hookType pubsub
hookType webhook

CreateEventHookResponse

{
  "eventHook": {
    "id": "bfc384726b6447a4b70a171de49e466f",
    "hookType": "webhook",
    "eventTypes": [
      "ct.entry"
    ],
    "status": "enabled",
    "destination": "https://hardenize.com/webhooks/receive",
    "secret": "3685c06a966e4d0ea625d0b475719661"
  }
}

Properties

Name Type Description
eventHook* EventHook Event hook objects contain information pertaining to a destination to which events are delivered (pushed).

CreateOrgRequest

{
  "id": "hardenize",
  "name": "Hardenize",
  "status": "active",
  "commercialStatus": "internal",
  "generateApiCredentials": true,
  "hostsAutoimportSubdomains": true,
  "limitTotalHostsHard": -1
}

Properties

Name Type Description
id* string Unique ID used to refer to the organization. Also used in other places, for example as part of the URL that's used to acces the web application side of things. You can select any ID that doesn't already exist, but the syntax must match that of DNS labels, using only lowercase characters. The ID you supply here will be relative to the ID of the parent organization, which means that you have the entire namespace to use how you wish.
name string Organization name is typically what will be shown in user interfaces. If not provided in the request, id will be used as display name.
status string The initial status the organization should have. Default: active.
commercialStatus string The initial commercial status for the new organization. Default: internal.
generateApiCredentials boolean If set, creates new API credentials for the organization. The API password must be stored by the caller, otherwise it will be lost. Default: false.
hostsAutoimportSubdomains boolean If set, newly discovered host that are subdomain of known hosts will be automatically added to the host inventory. Default: true.
limitTotalHostsHard integer Hard limit on the number of monitored hosts in the account. Default: -1 (unlimited).

Enumerated Values

Property Value
status active
status dormant
status suspended
status deleted
commercialStatus free
commercialStatus internal
commercialStatus paying
commercialStatus trial

CreateOrgResponse

{
  "org": {
    "id": "hardenize",
    "name": "Hardenize",
    "status": "active",
    "commercialStatus": "internal",
    "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
    "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
    "hostsAutoimportSubdomains": true,
    "limitTotalHostsHard": -1
  }
}

Properties

Name Type Description
org* Organization none

CreateGroupRequest

{
  "id": "production",
  "name": "Production"
}

Properties

Name Type Description
id* string The unique identifier for the group you wish to create. Group IDs are used for URL construction, and, as a result, the character set is fairly restricted; we allow ASCII letters and digits only, as well as dashes as separators.
name string Display name, typically used for human interaction. If not provided, the identifier will be used to populate it.

CreateGroupResponse

{
  "group": {
    "id": "production",
    "name": "Production"
  }
}

Properties

Name Type Description
group* Group The Group object represents one account group.

DeleteHostsRequest

{
  "hostnames": [
    "example.com"
  ],
  "subdomains": true,
  "preview": true
}

Properties

Name Type Description
hostnames* [string] List of hosts to delete.
subdomains boolean If set, indicates that the operation should apply to all the subdomains of the specified hosts. Default: false
preview boolean If set, this parameter enables preview mode, which means that no hosts will be deleted. Instead, the response will include the list of hosts that would have been deleted. Default: false.

DeleteHostsResponse

{
  "hostnames": [
    "example.com"
  ],
  "preview": true
}

Properties

Name Type Description
hostnames* [string] List of hosts that have been deleted (or would have been deleted, in preview mode).
preview* boolean Indicates if the action was executed or only previewed.

Event

{
  "id": 10001,
  "type": "ct",
  "createdOn": "2019-06-19T08:23:49.977Z",
  "apiVersion": "0.14.0",
  "data": {
    "field": "value"
  }
}

Event objects are created in response to various things of interest that happen in your account. They are designed to be a generic storage and retrieval system that can carry arbitrary embedded objects, which are encoded in JSON format. The type fields is used as indicator as to which embedded object is stored in the data field. We also record the version of the API at the time the data object was created. Should there be differences in the format, you can use the apiVersion field to determine exactly how the data should be handled.

Properties

Name Type Description
id* integer none
type* string none
createdOn* date-time none
apiVersion* string none
data* string none

EventDestination

{
  "destinationId": "pubsub://events/1/1005",
  "type": "pubsub",
  "project": "hz-events-pubsub",
  "topic": "projects/hz-events-pubsub/topics/ep-1-1005",
  "subscription": "ep-1-1005",
  "subscriberCredentials": "{\"type\": \"service_account\", \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\", \"client_id\": \"213792179274932\", \"token_uri\": \"https://oauth2.googleapis.com/token\", \"project_id\": \"hz-events-pubsub\", \"private_key\": \"-----BEGIN PRIVATE KEY-----\\n[REMOVED]\\n-----END PRIVATE KEY-----\\n\", \"client_email\": \"ep-1-1005@hz-events-pubsub.iam.gserviceaccount.com\", \"private_key_id\": \"b407bd79213dc1867aa45ab41e4e955961504f37\", \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/ep-1-1005%40hz-events-pubsub.iam.gserviceaccount.com\", \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\"}"
}

Contains information about one destination that can be used to receive events.

Properties

Name Type Description
destinationId* string Unique system-generated identifier.
type* string Destination type. Different fields may be available depending on this value.
project string PubSub project name.
topic string PubSub topic name.
subscription string PubSub subscription name.
subscriberCredentials string Contains raw Google GCP service account file that should be used to authenticate when retrieving from the subscription associated with this destination.

Enumerated Values

Property Value
type pubsub

EventHook

{
  "id": "bfc384726b6447a4b70a171de49e466f",
  "hookType": "webhook",
  "eventTypes": [
    "ct.entry"
  ],
  "status": "enabled",
  "destination": "https://hardenize.com/webhooks/receive",
  "secret": "3685c06a966e4d0ea625d0b475719661"
}

Event hook objects contain information pertaining to a destination to which events are delivered (pushed).

Properties

Name Type Description
id* string Contains the system-generated event hook identifier. This value is strongly random and, because it's provided with every event, can be used for an easy security check on the receiving end.
hookType* string Contains hook type.
eventTypes* [string] Contains the list of event types that will be sent to this hook.
status* string Indicates the current status of the event hook. The normal states are enabled and disabled. If a hook is determine to be inoperational, we will automatically disable it and change its state to failed.
destination string Contains the destination where events will be sent.
secret* string Contains a strongly random secret value unique to this hook. Used to sign events on delivery.

Enumerated Values

Property Value
hookType pubsub
hookType webhook
status enabled
status disabled
status failed

EventType

{
  "name": "ct",
  "available": true,
  "enabled": true
}

Every event we generate has a type, making it easier to distinguish one class of event from another, and to correctly process them.

Properties

Name Type Description
name* string none
available* boolean Specifies whether the account supports generation of this type of event.
enabled* boolean Specifies whether events of this type are currently being generated.

ErrorMessage

{
  "param": "string",
  "message": "string"
}

One instance of this object is returned for every problem encountered during request processing. If the object includes parameter name, the problem is related to that parameter, otherwise the problem applies to the request as a whole.

Properties

Name Type Description
param string none
message* string none

ErrorResponse

{
  "errors": [
    {
      "param": "string",
      "message": "string"
    }
  ]
}

This object is returned whenever a processing error occurs. It contains a list of error messages, some of which may be attributed to specific request parameters.

Properties

Name Type Description
errors* [ErrorMessage] [One instance of this object is returned for every problem encountered during request processing. If the object includes parameter name, the problem is related to that parameter, otherwise the problem applies to the request as a whole. ]

GetCertResponse

{
  "cert": {
    "sha256": "572908a23e5765a5e64fe06c775075133879ff9eed6e7135ced12e124edeca34\"",
    "tbsSha256": "7d63c93bbbf6d4f7aa492963dccd1ff14b35257b8eca4d912faa0ac1883a92da",
    "subject": "CN=ssl760680.cloudflaressl.com, OU=PositiveSSL Multi-Domain, OU=Domain Control Validated",
    "serial": "d0e65b67fe58f4a5d649cfaa3bb3c2fb",
    "issuer": "CN=COMODO ECC Domain Validation Secure Server CA 2, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB",
    "notBefore": "2019-06-19T08:23:49.978Z",
    "notAfter": "2019-06-19T08:23:49.978Z",
    "effectiveNotAfter": "2019-06-19T08:23:49.978Z",
    "revokedOn": "2019-06-19T08:23:49.978Z",
    "keyAlg": "EC",
    "keyLen": 256,
    "keyStrength": 128,
    "sigAlg": "ECDSAwithSHA256",
    "spkiSha256": "56c17eb4e3d510f7020e142cd36f617b38f93c26c72cc13dfebfbeed3e554382",
    "hosts": [
      "*.hardenize.com"
    ],
    "caPathLen": -1,
    "wildcard": true,
    "selfSigned": false,
    "firstSeen": "2019-06-19T08:23:49.978Z",
    "lastSeen": "2019-06-19T08:23:49.978Z",
    "seenInstalled": true,
    "active": true,
    "precert": false,
    "duplicate": false,
    "managed": true,
    "ownership": "own",
    "matchesOrgHost": true,
    "symantecStatus": "notSymantec",
    "ctRequired": true,
    "ctCompliant": true,
    "ctLogs": [
      {
        "log": "ct.googleapis.com/rocketeer",
        "timestamp": 1533791245857,
        "index": 232455,
        "sources": [
          "cert",
          "log"
        ]
      }
    ],
    "pem": "MIID/TCCA6OgAwIBAgIRANDmW2f+WPSl1knPqjuzwvswCgYIKoZIzj0EAwIwgZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQDEy9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EgMjAeFw0xODAzMDEwMDAwMDBaFw0xODA5MDcyMzU5NTlaMGwxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVsdGktRG9tYWluMSQwIgYDVQQDExtzc2w3NjA2ODAuY2xvdWRmbGFyZXNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjQmXlPI8fSFxAgBabWaZ/llDVh0Qvs6bEDqgu6Ny63HMiW6tXpBpnJs//B2Jysf4vFP2WaxHjD/CwhXyBiylso4IB/TCCAfkwHwYDVR0jBBgwFoAUQAlhZ/C8g3FP3hIILG/U1Ct2PZYwHQYDVR0OBBYEFNsOUClkQN7Qw/9QyXJMVcU+NVA1MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEBAgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMAgGBmeBDAECATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBMi5jcmwwgYgGCCsGAQUFBwEBBHwwejBRBggrBgEFBQcwAoZFaHR0cDovL2NydC5jb21vZG9jYTQuY29tL0NPTU9ET0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQTIuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMEYGA1UdEQQ/MD2CG3NzbDc2MDY4MC5jbG91ZGZsYXJlc3NsLmNvbYIPKi5oYXJkZW5pemUuY29tgg1oYXJkZW5pemUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDebJoLRDhbiDQSDWAb8+C2IkT3sXuL7nH0BYuxHiO32AIgf9YXFRRrzis/p7HVd9X2pkP4CxvriyrLQwpB6s2RFQM=",
    "origin": "ct",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "parentHashes": [
      "25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d",
      "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739"
    ],
    "parentHashesSource": "ct",
    "parentHashesComplete": true
  }
}

Properties

Name Type Description
cert* Certificate none

GetEventResponse

{
  "event": {
    "id": 10001,
    "type": "ct",
    "createdOn": "2019-06-19T08:23:49.978Z",
    "apiVersion": "0.14.0",
    "data": {
      "field": "value"
    }
  }
}

Properties

Name Type Description
event* Event Event objects are created in response to various things of interest that happen in your account. They are designed to be a generic storage and retrieval system that can carry arbitrary embedded objects, which are encoded in JSON format. The type fields is used as indicator as to which embedded object is stored in the data field. We also record the version of the API at the time the data object was created. Should there be differences in the format, you can use the apiVersion field to determine exactly how the data should be handled.

GetHostDiscoveryResponse

{
  "hostDiscovery": {
    "id": 11113,
    "autoResolved": false,
    "discoveredHostname": "www.🔥.hardenize.com",
    "discoveredTime": "2019-06-19T08:23:49.978Z",
    "effectiveHostname": "🔥.hardenize.com",
    "origin": "hdb",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "matchReason": "keyword",
    "resolution": "pending",
    "updatedTime": "2019-06-19T08:23:49.978Z"
  }
}

Properties

Name Type Description
hostDiscovery* HostDiscovery This object represents our discovery of a host which might be relevant to your organization.

GetHostDiscoveryKeywordResponse

{
  "hostDiscoveryKeyword": {
    "keyword": "hardenize"
  }
}

Properties

Name Type Description
hostDiscoveryKeyword* HostDiscoveryKeyword A keyword used for host discovery.

GetOrgResponse

{
  "suborg": {
    "id": "hardenize",
    "name": "Hardenize",
    "status": "active",
    "commercialStatus": "internal",
    "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
    "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
    "hostsAutoimportSubdomains": true,
    "limitTotalHostsHard": -1
  }
}

Properties

Name Type Description
suborg Organization none

Group

{
  "id": "production",
  "name": "Production"
}

The Group object represents one account group.

Properties

Name Type Description
id* string none
name* string none

Host

{
  "hostname": "🔥.hardenize.com",
  "punyHostname": "xn--4v8h.hardenize.com",
  "createdOn": "2019-06-19T08:23:49.979Z",
  "status": "archived",
  "origin": "hdb",
  "originInfo": {
    "net": {
      "host": "aspmx.l.google.com",
      "address": "2a00:1450:400c:c00:0:0:0:1b",
      "port": 25,
      "protocol": "smtp"
    }
  },
  "nx": true,
  "nxTime": "2019-06-19T08:23:49.979Z",
  "lastAssessmentTime": "2019-06-19T08:23:49.979Z",
  "assessmentError": "Host not found",
  "lastAssessmentAttemptTime": "2019-06-19T08:23:49.979Z"
}

The Host object represents one of your hosts that resides in our database.

Properties

Name Type Description
hostname* string none
punyHostname string none
createdOn* date-time none
status* string This host's monitoring status.
origin* string Indication of where this host came from.
originInfo OriginInfo Further information about the origin. For example, if the origin is cert, then this field will identify the actual certificate.
nx* boolean If nx is true, this signifies that the last time we tried to look the host up in the DNS, we failed.
nxTime date-time When nx is true, this field contains the date and time that we last failed to look the host up in the DNS.
lastAssessmentTime date-time The time of the last successful assessment.
assessmentError string Error message, which is available only if the last assessment resulted in an error.
lastAssessmentAttemptTime date-time When was the last assessment attempted?

Enumerated Values

Property Value
status archived
status idle
status monitored
origin cert
origin ct
origin hdb
origin manual

HostDiscovery

{
  "id": 11113,
  "autoResolved": false,
  "discoveredHostname": "www.🔥.hardenize.com",
  "discoveredTime": "2019-06-19T08:23:49.979Z",
  "effectiveHostname": "🔥.hardenize.com",
  "origin": "hdb",
  "originInfo": {
    "net": {
      "host": "aspmx.l.google.com",
      "address": "2a00:1450:400c:c00:0:0:0:1b",
      "port": 25,
      "protocol": "smtp"
    }
  },
  "matchReason": "keyword",
  "resolution": "pending",
  "updatedTime": "2019-06-19T08:23:49.979Z"
}

This object represents our discovery of a host which might be relevant to your organization.

Properties

Name Type Description
id* integer A unique identifier which you can use to refer to a particular host discovery when updating
autoResolved* boolean We may have automatically resolved your discovery. If we have, this will be set to true
discoveredHostname* string The hostname that we discovered, that we think might be relevant to you
discoveredTime date-time The date and time that we made this particular discovery
effectiveHostname* string The discovered hostname might be "www.🔥.hardenize.com", but you might just want to tell us that "🔥.hardenize.com" belongs to you, or even "hardenize.com". If so, you can set this value. It defaults to the same as discoveredHostname.
origin* string The location at which we discovered the hostname.
originInfo OriginInfo Further information about the origin.
matchReason* string The reason that we decided the hostname might be relevant to you.
resolution* string The current resolution state of the discovery. This is usually set to "pending" to indicate that you should resolve the discovery in some manner.
updatedTime date-time The date and time that this discovery was last updated

Enumerated Values

Property Value
origin cert
origin ct
origin hdb
origin manual
matchReason keyword
resolution pending
resolution own
resolution supplier
resolution unrelated
resolution infringing
resolution phishing

HostDiscoveryKeyword

{
  "keyword": "hardenize"
}

A keyword used for host discovery.

Properties

Name Type Description
keyword string The text to match with. Must consist of only lowercase letters, digits, dashes, and periods. It also must contain at least 5 characters and not more than 32.

ListCertsResponse

{
  "certs": [
    {
      "sha256": "572908a23e5765a5e64fe06c775075133879ff9eed6e7135ced12e124edeca34\"",
      "tbsSha256": "7d63c93bbbf6d4f7aa492963dccd1ff14b35257b8eca4d912faa0ac1883a92da",
      "subject": "CN=ssl760680.cloudflaressl.com, OU=PositiveSSL Multi-Domain, OU=Domain Control Validated",
      "serial": "d0e65b67fe58f4a5d649cfaa3bb3c2fb",
      "issuer": "CN=COMODO ECC Domain Validation Secure Server CA 2, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB",
      "notBefore": "2019-06-19T08:23:49.979Z",
      "notAfter": "2019-06-19T08:23:49.979Z",
      "effectiveNotAfter": "2019-06-19T08:23:49.979Z",
      "revokedOn": "2019-06-19T08:23:49.979Z",
      "keyAlg": "EC",
      "keyLen": 256,
      "keyStrength": 128,
      "sigAlg": "ECDSAwithSHA256",
      "spkiSha256": "56c17eb4e3d510f7020e142cd36f617b38f93c26c72cc13dfebfbeed3e554382",
      "hosts": [
        "*.hardenize.com"
      ],
      "caPathLen": -1,
      "wildcard": true,
      "selfSigned": false,
      "firstSeen": "2019-06-19T08:23:49.979Z",
      "lastSeen": "2019-06-19T08:23:49.979Z",
      "seenInstalled": true,
      "active": true,
      "precert": false,
      "duplicate": false,
      "managed": true,
      "ownership": "own",
      "matchesOrgHost": true,
      "symantecStatus": "notSymantec",
      "ctRequired": true,
      "ctCompliant": true,
      "ctLogs": [
        {
          "log": "ct.googleapis.com/rocketeer",
          "timestamp": 1533791245857,
          "index": 232455,
          "sources": [
            "cert",
            "log"
          ]
        }
      ],
      "pem": "MIID/TCCA6OgAwIBAgIRANDmW2f+WPSl1knPqjuzwvswCgYIKoZIzj0EAwIwgZIxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQDEy9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0EgMjAeFw0xODAzMDEwMDAwMDBaFw0xODA5MDcyMzU5NTlaMGwxITAfBgNVBAsTGERvbWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVsdGktRG9tYWluMSQwIgYDVQQDExtzc2w3NjA2ODAuY2xvdWRmbGFyZXNzbC5jb20wWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASjQmXlPI8fSFxAgBabWaZ/llDVh0Qvs6bEDqgu6Ny63HMiW6tXpBpnJs//B2Jysf4vFP2WaxHjD/CwhXyBiylso4IB/TCCAfkwHwYDVR0jBBgwFoAUQAlhZ/C8g3FP3hIILG/U1Ct2PZYwHQYDVR0OBBYEFNsOUClkQN7Qw/9QyXJMVcU+NVA1MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBPBgNVHSAESDBGMDoGCysGAQQBsjEBAgIHMCswKQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMAgGBmeBDAECATBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNlcnZlckNBMi5jcmwwgYgGCCsGAQUFBwEBBHwwejBRBggrBgEFBQcwAoZFaHR0cDovL2NydC5jb21vZG9jYTQuY29tL0NPTU9ET0VDQ0RvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQTIuY3J0MCUGCCsGAQUFBzABhhlodHRwOi8vb2NzcC5jb21vZG9jYTQuY29tMEYGA1UdEQQ/MD2CG3NzbDc2MDY4MC5jbG91ZGZsYXJlc3NsLmNvbYIPKi5oYXJkZW5pemUuY29tgg1oYXJkZW5pemUuY29tMAoGCCqGSM49BAMCA0gAMEUCIQDebJoLRDhbiDQSDWAb8+C2IkT3sXuL7nH0BYuxHiO32AIgf9YXFRRrzis/p7HVd9X2pkP4CxvriyrLQwpB6s2RFQM=",
      "origin": "ct",
      "originInfo": {
        "net": {
          "host": "aspmx.l.google.com",
          "address": "2a00:1450:400c:c00:0:0:0:1b",
          "port": 25,
          "protocol": "smtp"
        }
      },
      "parentHashes": [
        "25847d668eb4f04fdd40b12b6b0740c567da7d024308eb6c2c96fe41d9de218d",
        "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739"
      ],
      "parentHashesSource": "ct",
      "parentHashesComplete": true
    }
  ]
}

Properties

Name Type Description
certs* [Certificate] none

ListEventDestinationsResponse

{
  "eventDestinations": [
    {
      "destinationId": "pubsub://events/1/1005",
      "type": "pubsub",
      "project": "hz-events-pubsub",
      "topic": "projects/hz-events-pubsub/topics/ep-1-1005",
      "subscription": "ep-1-1005",
      "subscriberCredentials": "{\"type\": \"service_account\", \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\", \"client_id\": \"213792179274932\", \"token_uri\": \"https://oauth2.googleapis.com/token\", \"project_id\": \"hz-events-pubsub\", \"private_key\": \"-----BEGIN PRIVATE KEY-----\\n[REMOVED]\\n-----END PRIVATE KEY-----\\n\", \"client_email\": \"ep-1-1005@hz-events-pubsub.iam.gserviceaccount.com\", \"private_key_id\": \"b407bd79213dc1867aa45ab41e4e955961504f37\", \"client_x509_cert_url\": \"https://www.googleapis.com/robot/v1/metadata/x509/ep-1-1005%40hz-events-pubsub.iam.gserviceaccount.com\", \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\"}"
    }
  ]
}

Properties

Name Type Description
eventDestinations* [EventDestination] [Contains information about one destination that can be used to receive events. ]

ListEventHooksResponse

{
  "eventHooks": [
    {
      "id": "bfc384726b6447a4b70a171de49e466f",
      "hookType": "webhook",
      "eventTypes": [
        "ct.entry"
      ],
      "status": "enabled",
      "destination": "https://hardenize.com/webhooks/receive",
      "secret": "3685c06a966e4d0ea625d0b475719661"
    }
  ]
}

Properties

Name Type Description
eventHooks* [EventHook] [Event hook objects contain information pertaining to a destination to which events are delivered (pushed). ]

ListEventsResponse

{
  "events": [
    {
      "id": 10001,
      "type": "ct",
      "createdOn": "2019-06-19T08:23:49.980Z",
      "apiVersion": "0.14.0",
      "data": {
        "field": "value"
      }
    }
  ]
}

Properties

Name Type Description
events* [Event] [Event objects are created in response to various things of interest that happen in your account. They are designed to be a generic storage and retrieval system that can carry arbitrary embedded objects, which are encoded in JSON format. The type fields is used as indicator as to which embedded object is stored in the data field. We also record the version of the API at the time the data object was created. Should there be differences in the format, you can use the apiVersion field to determine exactly how the data should be handled. ]

ListEventTypesResponse

{
  "eventTypes": [
    {
      "name": "ct",
      "available": true,
      "enabled": true
    }
  ]
}

Properties

Name Type Description
eventTypes* [EventType] [Every event we generate has a type, making it easier to distinguish one class of event from another, and to correctly process them. ]

ListHostResponse

{
  "host": [
    {
      "hostname": "🔥.hardenize.com",
      "punyHostname": "xn--4v8h.hardenize.com",
      "createdOn": "2019-06-19T08:23:49.980Z",
      "status": "archived",
      "origin": "hdb",
      "originInfo": {
        "net": {
          "host": "aspmx.l.google.com",
          "address": "2a00:1450:400c:c00:0:0:0:1b",
          "port": 25,
          "protocol": "smtp"
        }
      },
      "nx": true,
      "nxTime": "2019-06-19T08:23:49.980Z",
      "lastAssessmentTime": "2019-06-19T08:23:49.980Z",
      "assessmentError": "Host not found",
      "lastAssessmentAttemptTime": "2019-06-19T08:23:49.980Z"
    }
  ]
}

Properties

Name Type Description
host* [Host] [The Host object represents one of your hosts that resides in our database.]

ListHostsResponse

{
  "hosts": {
    "hostname": "🔥.hardenize.com",
    "punyHostname": "xn--4v8h.hardenize.com",
    "createdOn": "2019-06-19T08:23:49.981Z",
    "status": "archived",
    "origin": "hdb",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "nx": true,
    "nxTime": "2019-06-19T08:23:49.981Z",
    "lastAssessmentTime": "2019-06-19T08:23:49.981Z",
    "assessmentError": "Host not found",
    "lastAssessmentAttemptTime": "2019-06-19T08:23:49.981Z"
  }
}

Properties

Name Type Description
hosts* Host The Host object represents one of your hosts that resides in our database.

ListHostDiscoveriesResponse

{
  "hostDiscoveries": [
    {
      "id": 11113,
      "autoResolved": false,
      "discoveredHostname": "www.🔥.hardenize.com",
      "discoveredTime": "2019-06-19T08:23:49.981Z",
      "effectiveHostname": "🔥.hardenize.com",
      "origin": "hdb",
      "originInfo": {
        "net": {
          "host": "aspmx.l.google.com",
          "address": "2a00:1450:400c:c00:0:0:0:1b",
          "port": 25,
          "protocol": "smtp"
        }
      },
      "matchReason": "keyword",
      "resolution": "pending",
      "updatedTime": "2019-06-19T08:23:49.981Z"
    }
  ]
}

Properties

Name Type Description
hostDiscoveries* [HostDiscovery] [This object represents our discovery of a host which might be relevant to your organization.]

ListHostDiscoveryKeywordsResponse

{
  "hostDiscoveryKeywords": [
    {
      "keyword": "hardenize"
    }
  ]
}

Properties

Name Type Description
hostDiscoveryKeywords* [HostDiscoveryKeyword] [A keyword used for host discovery.]

ListOrgsResponse

{
  "orgs": [
    {
      "id": "hardenize",
      "name": "Hardenize",
      "status": "active",
      "commercialStatus": "internal",
      "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
      "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
      "hostsAutoimportSubdomains": true,
      "limitTotalHostsHard": -1
    }
  ]
}

Properties

Name Type Description
orgs* [Organization] none

ListReports0Response

{
  "reports": [
    {
      "hostname": "example.com",
      "status": "completed",
      "reportTime": "2018-10-10T15:36:49.044Z",
      "hasDnssec": true,
      "hasSmtp": true,
      "hasSmtpTls": true,
      "hasSmtpDane": true,
      "hasSpf": true,
      "hasDmarc": true,
      "hasHttp": true,
      "hasHttps": true,
      "hasHttpsDane": true,
      "hasHttpRedirection": true,
      "hasHsts": true,
      "hasHstsPreloaded": true,
      "nameServers": "string",
      "dnssec": "string",
      "emailTls": "string",
      "emailDane": "string",
      "spf": "string",
      "dmarc": "string",
      "wwwTls": "string",
      "wwwDane": "string",
      "hsts": "string",
      "hpkp": "string",
      "cookies": "string",
      "mixedContent": "string",
      "securityHeaders": "string",
      "csp": "string"
    }
  ]
}

Properties

Name Type Description
reports* [Report0] [Contains a summary of one Hardenize assessment. The available fields fall into one of two categories. In the first category are boolean fields that indicate if a particular feature is present, for example, hasTls and hasHsts. In the second category are the fields that describe the quality of the configuration. These fields will take self-descriptive values such as error, warning, and good. The complete explanation of the possible values is available in the Report0Quality component. It is possible that a field is not present, which happens when the neither true nor false make sense. For example, if a host doesn't support TLS, the hasHsts field will not be in the report. ]

ListGroupsResponse

{
  "groups": [
    {
      "id": "production",
      "name": "Production"
    }
  ]
}

Properties

Name Type Description
groups* [Group] [The Group object represents one account group.]

MatchedCtEntry

{
  "log": "ct.googleapis.com/icarus",
  "index": 251676662,
  "timestamp": 1538747492396,
  "sha256": "7b72bbe8b7faeea24d9bd8ded5f057114a14ad503b33022b54b16603a8b074b7",
  "precert": false,
  "subject": "CN=www.example.com",
  "issuer": "C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3",
  "hosts": [
    "example.com"
  ],
  "chain": [
    "MIIGJTCCBQ2gAwIBAgISA9CTYlAcEi7o1Cyk3RM9D6/JMA0GCSqGSIb3DQEBCwUAMEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQDExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xODA1MDIxMTA2NTdaFw0xODA3MzExMTA2NTdaMBwxGjAYBgNVBAMTEWJvbm4tMDYucWx1ZWQubmV0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy+muYgsZOUD2epeJwP6ToDmE6YeO9T+gsf9ACuLbrQqC5JZPy+AmREuo3dU3dkmBRoU9Brpmo/KMQavKueGVW3DpAIJKemGBC0yWNFgTho4+DAOvSM4odcB96HPFIh0vp13LH5og/wsNZwt+n56mrUTrcqnZYbUwugBghb0QCptwCnHnKOk2/YdRRraasgmiFWYeNjCqBUR5iKqmubgBoCqqkBYzWUhjWc7aySKYQFpSlZ2d3t0IilJp5sZq5pDiHa58G6fGZSh9TIAZvuvozW762cghBZgEF3wlvKy1joSAWLalPYQcsd0v2G9F7vJOu6Rf9HAbmdKqnu0i8TExjwIDAQABo4IDMTCCAy0wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQlgfnFoFLAegwCUrKiuz+Nu61SCDAfBgNVHSMEGDAWgBSoSmpjBH3duubRObemRWXv86jsoTBvBggrBgEFBQcBAQRjMGEwLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3NwLmludC14My5sZXRzZW5jcnlwdC5vcmcwLwYIKwYBBQUHMAKGI2h0dHA6Ly9jZXJ0LmludC14My5sZXRzZW5jcnlwdC5vcmcvMDMGA1UdEQQsMCqCEWJvbm4tMDYucWx1ZWQubmV0ghV3d3cuYm9ubi0wNi5xbHVlZC5uZXQwgf4GA1UdIASB9jCB8zAIBgZngQwBAgEwgeYGCysGAQQBgt8TAQEBMIHWMCYGCCsGAQUFBwIBFhpodHRwOi8vY3BzLmxldHNlbmNyeXB0Lm9yZzCBqwYIKwYBBQUHAgIwgZ4MgZtUaGlzIENlcnRpZmljYXRlIG1heSBvbmx5IGJlIHJlbGllZCB1cG9uIGJ5IFJlbHlpbmcgUGFydGllcyBhbmQgb25seSBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIENlcnRpZmljYXRlIFBvbGljeSBmb3VuZCBhdCBodHRwczovL2xldHNlbmNyeXB0Lm9yZy9yZXBvc2l0b3J5LzCCAQUGCisGAQQB1nkCBAIEgfYEgfMA8QB3ANt0r+7LKeyx/so+cW0s5bmquzb3hHGDx12dTze2H79kAAABYyC/mssAAAQDAEgwRgIhAMnyq3/kzpvp7LcXm3JqeCjh1dMB0fZTv9pIvpPCS4GPAiEA9f+JLP1KKuaXnwr3rin4Y8tBG8a10YGaKT3RnJOs7wIAdgApPFGWVMg5ZbqqUPxYB9S3b79Yeily3KTDDPTlRUf0eAAAAWMgv5reAAAEAwBHMEUCIA1jzhkoel+MFmVIdspCwyKVdzZZsBwx8WiJixPju9ELAiEA4Xw2ABUkt3IK67G+GrABu1Ik+R/7BVFjo3GvMIRBJ+AwDQYJKoZIhvcNAQELBQADggEBAHKPt1cq8LEy0wmtmBoThNL6AevJz2WM/KRKBYvEHiXcLN3Z9a1eQ6c8g4A84AARBDgXUfkc3W29AIW0A5wTLVazUE5H7bIoiQJXT2Z6KMXxFqwx5pRu8f1oXUx3xLhJoHkDEGrbD5uy7j9bI25pI9g5obAY88es8ZFJz25PEozA2R/NpXZEnHVbvyOHx4Pr6z3ctuH+WWpK96jWEMBP5pAx5qXBYI5g9bHGy2nYuuq0ZIuOPVK1k7SlctBrrBJx2q1ANUaEfIyPjd2qsjfoI5//6Jn+jHDM1XrdvZ+7S60SDqXktwHS98o5jRZnGWLu1S6nVcHWQzjPBhiSvAukuJw=",
    "MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0NlowSjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMTGkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EFq6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWAa6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIGCCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNvbTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9kc3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAwVAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcCARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwuY3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsFAAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJouM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwuX4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlGPfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg=="
  ],
  "matchedHosts": [
    "example.com"
  ]
}

Contains information extracted from a CT log entry that had been matched against an account and imported.

Properties

Name Type Description
log* string CT log URL, with the scheme omitted.
index* integer(int64) Milliseconds since January 1, 1970, excluding leap seconds, per CT RFC.
timestamp* integer(int64) This certificate's index in the referenced CT log.
sha256* string SHA256 hash of the leaf certificate/precertificate.
precert* boolean Indicator of whether the leaf is a precertificate.
subject* string Certificate subject Distinguished Name in text format.
issuer* string Certificate issuer Distinguished Name in text format.
hosts* [string] Hostnames and IP addresses extracted from the leaf certificate.
chain* [string] Certificate chain stored in the matched CT log entry.
matchedHosts* [string] List of account hosts that were matched against the CT log entry.

OriginInfo

{
  "net": {
    "host": "aspmx.l.google.com",
    "address": "2a00:1450:400c:c00:0:0:0:1b",
    "port": 25,
    "protocol": "smtp"
  }
}

Properties

Name Type Description
net OriginInfoNet none

OriginInfoNet

{
  "host": "aspmx.l.google.com",
  "address": "2a00:1450:400c:c00:0:0:0:1b",
  "port": 25,
  "protocol": "smtp"
}

Properties

Name Type Description
host string Network hostname, when available.
address* string Network IPv4 or IPv6 address.
port* integer Network port.
protocol* string Network protocol.

Organization

{
  "id": "hardenize",
  "name": "Hardenize",
  "status": "active",
  "commercialStatus": "internal",
  "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
  "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
  "hostsAutoimportSubdomains": true,
  "limitTotalHostsHard": -1
}

Properties

Name Type Description
id* string Unique ID of an organization. The value stored in this field is always relative to that of the parent organization. For example, if the parent's ID is hardenize and you created a new nested organization called prod, you will observe this shorter identifier in the API responses. If you wish to access the nested organization via the API, you will need to specify its full identifier, which would be hardenize.prod.
name* string Human-readable organization name.
status* string By default, an organization will be active immediately after it is created. If the status is changed to dormant, all operations and features in the account will be disabled, however the users will still be able to access the organization and the data in the account. If the status is changed to suspeneded, the organization will effectively become deleted from an external perspective. The deleted status is made available to enable delayed deletion of accounts. An organization with this status is expected to be deleted in the near future; for example, there could be a weekly process that obtains a list of all organizations scheduled for deletion and actually deletes them.
commercialStatus* string The commercialStatus field is used to track how a suborganization is used, for accounting and billing purposes. When creating a suborganization, select the value that's the most appropriate. Update the value as the status changes (e.g., from trial to paying).
apiUsername string The username that can be used to access this organization's API.
apiPassword string The password that can be used to access this organization's API. Because we don't store plaintext in our database, this field is available only immediately after the organization is created.
hostsAutoimportSubdomains* boolean Determines if newly discovered subdomains (of known organization hosts) will be automatically added to the inventory.
limitTotalHostsHard* integer Determines if there is a limit on the number of monitored hosts in the account. Set to -1 when there is no limit.

Enumerated Values

Property Value
status active
status dormant
status suspended
status deleted
commercialStatus free
commercialStatus internal
commercialStatus paying
commercialStatus trial

Report0

{
  "hostname": "example.com",
  "status": "completed",
  "reportTime": "2018-10-10T15:36:49.044Z",
  "hasDnssec": true,
  "hasSmtp": true,
  "hasSmtpTls": true,
  "hasSmtpDane": true,
  "hasSpf": true,
  "hasDmarc": true,
  "hasHttp": true,
  "hasHttps": true,
  "hasHttpsDane": true,
  "hasHttpRedirection": true,
  "hasHsts": true,
  "hasHstsPreloaded": true,
  "nameServers": "string",
  "dnssec": "string",
  "emailTls": "string",
  "emailDane": "string",
  "spf": "string",
  "dmarc": "string",
  "wwwTls": "string",
  "wwwDane": "string",
  "hsts": "string",
  "hpkp": "string",
  "cookies": "string",
  "mixedContent": "string",
  "securityHeaders": "string",
  "csp": "string"
}

Contains a summary of one Hardenize assessment. The available fields fall into one of two categories. In the first category are boolean fields that indicate if a particular feature is present, for example, hasTls and hasHsts. In the second category are the fields that describe the quality of the configuration. These fields will take self-descriptive values such as error, warning, and good. The complete explanation of the possible values is available in the Report0Quality component.

It is possible that a field is not present, which happens when the neither true nor false make sense. For example, if a host doesn't support TLS, the hasHsts field will not be in the report.

Properties

Name Type Description
hostname* string none
status* string none
reportTime date-time none
hasDnssec boolean none
hasSmtp boolean none
hasSmtpTls boolean none
hasSmtpDane boolean none
hasSpf boolean none
hasDmarc boolean none
hasHttp boolean none
hasHttps boolean none
hasHttpsDane boolean none
hasHttpRedirection boolean none
hasHsts boolean none
hasHstsPreloaded boolean none
nameServers string(v0quality) none
dnssec string(v0quality) none
emailTls string(v0quality) none
emailDane string(v0quality) none
spf string(v0quality) none
dmarc string(v0quality) none
wwwTls string(v0quality) none
wwwDane string(v0quality) none
hsts string(v0quality) none
hpkp string(v0quality) none
cookies string(v0quality) none
mixedContent string(v0quality) none
securityHeaders string(v0quality) none
csp string(v0quality) none

Enumerated Values

Property Value
status completed
status failed
status notAvailable

Report0Quality

{
  "quality": "good"
}

This field describes the quality of configuration of particular element. The four most commonly seen values here are good, warning, error, and neutral. Out of these, the best is cleary good, but neutral is all right, depending on your policies (e.g., you might not want to deploy a particular security technology). Hardenize uses warnings and errors only when something is broken, misconfigured, or has a negative security implication. Neither of these qualities is used if you don't have a particular security feature. We use unknown if we don't have enough information to make a judgement. Finally, warningAbsent and errorAbsent are special statuses that we use to indicate when warnings and errors are indicated due to absence of feature. This might happen, for example, if a site supports plaintext HTTP but not encrypted HTTPS.

Properties

Name Type Description
quality string none

Enumerated Values

Property Value
quality good
quality error
quality errorAbsent
quality neutral
quality unknown
quality warning
quality warningAbsent

TestEventHookResponse

{
  "successful": false,
  "errorMessage": "Expected 202 or 204 status code",
  "durationMillis": 5814,
  "pubsub": {
    "destination": "pubsub://events/1/1005",
    "message": "{\"id\":0,\"createdOn\":\"2018-10-10T15:36:49.044Z\",\"type\":\"test\",\"data\":{\"message\":\"This is a webhook test.\"}}",
    "attributes": {
      "X-Hardenize-EventHookId": "74bf16db59ef4d55aeeb7fe9f7d5171d",
      "X-Hardenize-Org": "demo",
      "X-Hardenize-Signature": "t=1539185809044; hmac-sha256=64d386808229f5c84fac665fb6f9376f24efca2971b51713032dca6b83566fd8"
    },
    "messageId": 260486610038606
  },
  "webook": {
    "request": {
      "method": "POST",
      "url": "https://hardenize.com/webhooks/receive",
      "headers": {
        "Content-Type": "application/json;charset=UTF-8",
        "User-Agent": "Hardenize (https://www.hardenize.com)",
        "X-Hardenize-EventHookId": "74bf16db59ef4d55aeeb7fe9f7d5171d",
        "X-Hardenize-Org": "demo",
        "X-Hardenize-Signature": "t=1539185809044; hmac-sha256=64d386808229f5c84fac665fb6f9376f24efca2971b51713032dca6b83566fd8"
      },
      "body": "{\"id\":0,\"createdOn\":\"2018-10-10T15:36:49.044Z\",\"type\":\"test\",\"data\":{\"message\":\"This is a webhook test.\"}}"
    },
    "response": {
      "statusCode": 302,
      "headers": {
        "Location": "https://hardenize.com/redirection",
        "Cache-Control": "no-cache",
        "Connection": "keep-alive",
        "Content-Type": "text/plain; charset=UTF-8",
        "Date": "Wed, 10 Oct 2018 15:36:54 GMT",
        "Server": "nginx/1.10.3",
        "Transfer-Encoding": "chunked",
        "Vary": "Accept-Encoding"
      },
      "body": "OK"
    }
  }
}

Embeds a transcript of an event hook test, providing request and response information, as well as an indication of whether the hook is operating correctly.

Properties

Name Type Description
successful boolean Indication of whether the event hook test was successful. If the HTTP request itself is successful, the status code must be in the 2xx range. If the test is not successful, the errorMessage field will contain an explanation.
errorMessage string Error message, in case of test failure only.
durationMillis integer(int64) Duration of the HTTP request submitted to the hook, in milliseconds.
pubsub object Webhook-specific diagnostic information.
» destination string PubSub destination.
» message string Message body.
» attributes object Message attributes.
» messageId string PubSub message ID.
webook object Webhook-specific diagnostic information.
» request object Information about the submitted HTTP request, including some selected request headers.
»» method string Request method; always POST.
»» url string Webhook URL used for the test.
»» headers object Selected HTTP request headers.
»» body string Raw request body, as a string.
» response object Information about the HTTP response recived from the remote server.
»» statusCode integer HTTP response status code obtained from the remote server.
»» headers object Complete HTTP response headers received from the remote server.
»» body string Raw response body, as a string.

UpdateUserRequest

{
  "deleteMfa": true
}

Updates attributes for a user. No fields are required, but you need to provide at least one of the supported fields.

Properties

Name Type Description
deleteMfa boolean Will delete MFA for a user if it is enabled. Allowing them to log in using only their email address and password.

UpdateEventHookRequest

{
  "eventTypes": [
    "ct.entry"
  ],
  "destination": "https://hardenize.com/webhooks/receive",
  "status": "disabled"
}

Provides new field values to update an existing event hook. No fields are required, but you need to provide at least of the supported fields.

Properties

Name Type Description
eventTypes [string] An updated list of event types to send to this event hook.
destination string Event hook destination; for webhooks, this must be a HTTPS URL.
status string New event hook status.

Enumerated Values

Property Value
status enabled
status disabled
status failed

UpdateEventHookResponse

{
  "eventHook": {
    "id": "bfc384726b6447a4b70a171de49e466f",
    "hookType": "webhook",
    "eventTypes": [
      "ct.entry"
    ],
    "status": "enabled",
    "destination": "https://hardenize.com/webhooks/receive",
    "secret": "3685c06a966e4d0ea625d0b475719661"
  }
}

Returned after a successful event hook update operation.

Properties

Name Type Description
eventHook* EventHook Event hook objects contain information pertaining to a destination to which events are delivered (pushed).

UpdateEventTypeRequest

{
  "enabled": true
}

Properties

Name Type Description
enabled* boolean New setting for whether event type is enabled.

UpdateEventTypeResponse

{
  "eventType": {
    "name": "ct",
    "available": true,
    "enabled": true
  }
}

Properties

Name Type Description
eventType* EventType Every event we generate has a type, making it easier to distinguish one class of event from another, and to correctly process them.

UpdateHostDiscoveryResponse

{
  "hostDiscovery": {
    "id": 11113,
    "autoResolved": false,
    "discoveredHostname": "www.🔥.hardenize.com",
    "discoveredTime": "2019-06-19T08:23:49.983Z",
    "effectiveHostname": "🔥.hardenize.com",
    "origin": "hdb",
    "originInfo": {
      "net": {
        "host": "aspmx.l.google.com",
        "address": "2a00:1450:400c:c00:0:0:0:1b",
        "port": 25,
        "protocol": "smtp"
      }
    },
    "matchReason": "keyword",
    "resolution": "pending",
    "updatedTime": "2019-06-19T08:23:49.983Z"
  }
}

Properties

Name Type Description
hostDiscovery* HostDiscovery This object represents our discovery of a host which might be relevant to your organization.

UpdateHostsChanges

{
  "status": "monitored",
  "groupOp": "add",
  "groups": [
    "staging",
    "development"
  ]
}

Properties

Name Type Description
status string Desired host status.
groupOp string This parameter selects one of three tag operations. The add operation will add the specified tags to the hosts. The remove operation will remove the specified tags from the hosts. The set operation will first remove all existing tags from the hosts, then apply the specified tags. This field is mandatory when at least one group is specified.
groups [string] List of tags that should be used in the requested tag operation.

Enumerated Values

Property Value
status monitored
status idle
status archived
groupOp add
groupOp remove
groupOp set

UpdateHostDiscoveryRequest

{
  "resolution": "pending",
  "effectiveHostname": "🔥.hardenize.com"
}

Properties

Name Type Description
resolution* string If set, updates the discoveries resolution.
effectiveHostname string If set, updates the discoveries effectiveHostname. Must be equal to, or an ancestor of the discoveredHostname

Enumerated Values

Property Value
resolution pending
resolution own
resolution supplier
resolution unrelated
resolution infringing
resolution phishing

UpdateHostsRequest

{
  "hostnames": [
    "example.com"
  ],
  "preview": true,
  "subdomains": true,
  "changes": {
    "status": "monitored",
    "groupOp": "add",
    "groups": [
      "staging",
      "development"
    ]
  }
}

Properties

Name Type Description
hostnames* [string] List of hosts to update.
preview boolean If set, doesn't carry out the operation, but returns a list of hosts that would have been affected. Default: false
subdomains boolean If set, indicates that the operation should apply to all the subdomains of the specified hosts. Default: false
changes UpdateHostsChanges none

UpdateHostsResponse

{
  "hostnames": [
    "example.com"
  ],
  "preview": true
}

Properties

Name Type Description
hostnames* [string] List of hosts that have been updated (or would have been updated, in preview mode).
preview* boolean Indicates if the action was executed or only previewed.

UpdateOrgRequest

{
  "status": "active",
  "commercialStatus": "internal",
  "generateApiCredentials": true,
  "hostsAutoimportSubdomains": true,
  "limitTotalHostsHard": -1
}

Properties

Name Type Description
status string none
commercialStatus string none
generateApiCredentials boolean If set, creates new API credentials for the organization. The API password must be stored by the caller, otherwise it will be lost.
hostsAutoimportSubdomains boolean If provided, updates the corresponding organization setting.
limitTotalHostsHard integer If provided, updates the corresponding organization setting.

Enumerated Values

Property Value
status active
status dormant
status suspended
status deleted
commercialStatus free
commercialStatus internal
commercialStatus paying
commercialStatus trial

UpdateOrgResponse

{
  "suborg": {
    "id": "hardenize",
    "name": "Hardenize",
    "status": "active",
    "commercialStatus": "internal",
    "apiUsername": "59b71e9801f56c84a1bd537a448cf25c",
    "apiPassword": "3ccb5136c4b584a483cb77cf7111232f",
    "hostsAutoimportSubdomains": true,
    "limitTotalHostsHard": -1
  }
}

Properties

Name Type Description
suborg Organization none