[RFR]: Added Origin CA Certificate endpoint (#123)

* Added Certificate endpoint

* Implement all calls in /certificates endpoint

* Added to travis more php versions

* Fix package compatibility

* Added CertificateTest

* Added test for Certificate endpoint

* Added more tests

* Updated README

Co-authored-by: haphan <thanhha.phan@myrepublic.net>
This commit is contained in:
Ha Phan
2020-07-07 18:19:15 +08:00
committed by GitHub
parent fab493d2d3
commit 6d9b4ddffe
12 changed files with 654 additions and 240 deletions

View File

@@ -3,6 +3,15 @@ language: php
php: php:
- 7.0 - 7.0
- 7.1 - 7.1
- 7.2
- 7.3
- 7.4
- nightly
jobs:
allow_failures:
- php: 7.4
- php: nightly
before_install: before_install:
- composer self-update - composer self-update

View File

@@ -25,7 +25,7 @@ Each API call is provided via a similarly named function within various classes
- [ ] Organization Administration - [ ] Organization Administration
- [x] [Railgun](https://www.cloudflare.com/railgun/) administration - [x] [Railgun](https://www.cloudflare.com/railgun/) administration
- [ ] [Keyless SSL](https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/) - [ ] [Keyless SSL](https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/)
- [ ] [Origin CA](https://blog.cloudflare.com/universal-ssl-encryption-all-the-way-to-the-origin-for-free/) - [x] [Origin CA](https://blog.cloudflare.com/universal-ssl-encryption-all-the-way-to-the-origin-for-free/)
- [x] Crypto - [x] Crypto
- [x] Load Balancers - [x] Load Balancers
- [x] Firewall Settings - [x] Firewall Settings

View File

@@ -9,7 +9,7 @@
"ext-json": "*" "ext-json": "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "5.7.5", "phpunit/phpunit": "^5.7",
"phpmd/phpmd" : "@stable", "phpmd/phpmd" : "@stable",
"friendsofphp/php-cs-fixer": "^2.6" "friendsofphp/php-cs-fixer": "^2.6"
}, },

534
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,58 @@
<?php
namespace Cloudflare\API\Configurations;
class Certificate implements Configurations
{
const ORIGIN_RSA = 'origin-rsa';
const ORIGIN_ECC = 'origin-ecc';
const KEYLESS_CERTIFICATE = 'keyless-certificate';
private $config = [];
public function getArray(): array
{
return $this->config;
}
/**
* Array of hostnames or wildcard names (e.g., *.example.com) bound to the certificate
* Example: $hostnames = ["example.com", "foo.example.com"]
* @param array $hostnames
*/
public function setHostnames(array $hostnames)
{
$this->config['hostnames'] = $hostnames;
}
/**
* The number of days for which the certificate should be valid
* Default value: 5475
* Valid values: 7, 30, 90, 365, 730, 1095, 5475
* @param int $validity
*/
public function setRequestedValidity(int $validity)
{
$this->config['requested_validity'] = $validity;
}
/**
* Signature type desired on certificate ("origin-rsa" (rsa), "origin-ecc" (ecdsa), or "keyless-certificate" (for Keyless SSL servers)
* Valid values: origin-rsa, origin-ecc, keyless-certificate
* @param string $type
*/
public function setRequestType(string $type)
{
$this->config['request_type'] = $type;
}
/**
* The Certificate Signing Request (CSR). Must be newline-encoded.
*
* @param string $csr
*/
public function setCsr(string $csr)
{
$this->config['csr'] = $csr;
}
}

View File

@@ -0,0 +1,86 @@
<?php
namespace Cloudflare\API\Endpoints;
use Cloudflare\API\Adapter\Adapter;
use Cloudflare\API\Configurations\Certificate as CertificateConfig;
use Cloudflare\API\Traits\BodyAccessorTrait;
class Certificates implements API
{
use BodyAccessorTrait;
private $adapter;
public function __construct(Adapter $adapter)
{
$this->adapter = $adapter;
}
/**
* List all existing Origin CA certificates for a given zone
*
* @param string $zoneID
* @return array
*/
public function listCertificates(string $zoneID): \stdClass
{
$certificates = $this->adapter->get('certificates', ['zone_id' => $zoneID]);
$this->body = json_decode($certificates->getBody());
return (object)['result' => $this->body->result];
}
/**
* Get an existing Origin CA certificate by its serial number
*
* @param string $certificateID
* @param string $zoneID
* @return mixed
*/
public function getCertificate(string $certificateID, string $zoneID)
{
$certificates = $this->adapter->get('certificates/'.$certificateID, ['zone_id' => $zoneID]);
$this->body = json_decode($certificates->getBody());
return (object)['result' => $this->body->result];
}
/**
* Revoke an existing Origin CA certificate by its serial number
*
* @param string $certificateID
* @param string $zoneID
* @return bool
*/
public function revokeCertificate(string $certificateID, string $zoneID): bool
{
$certificates = $this->adapter->delete('certificates/'.$certificateID, ['zone_id' => $zoneID]);
$this->body = json_decode($certificates->getBody());
if (isset($this->body->result->id)) {
return true;
}
return false;
}
/**
* Create an Origin CA certificate
*
* @param CertificateConfig $config
* @return bool
*/
public function createCertificate(CertificateConfig $config): bool
{
$certificate = $this->adapter->post('certificates', $config->getArray());
$this->body = json_decode($certificate->getBody());
if (isset($this->body->result->id)) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,22 @@
<?php
use PHPUnit\Framework\TestCase;
use Cloudflare\API\Configurations\Certificate;
class CertificateTest extends TestCase
{
public function testGetArray()
{
$certificate = new Certificate();
$certificate->setHostnames(['foo.com', '*.bar.com']);
$certificate->setRequestType(Certificate::ORIGIN_ECC);
$certificate->setRequestedValidity(365);
$certificate->setCsr('some-csr-encoded-text');
$array = $certificate->getArray();
$this->assertEquals(['foo.com', '*.bar.com'], $array['hostnames']);
$this->assertEquals('origin-ecc', $array['request_type']);
$this->assertEquals(365, $array['requested_validity']);
$this->assertEquals('some-csr-encoded-text', $array['csr']);
}
}

View File

@@ -0,0 +1,120 @@
<?php
use Cloudflare\API\Endpoints\Certificates;
class CertificatesTest extends TestCase
{
public function testListCertificates()
{
$response = $this->getPsr7JsonResponseForFixture('Endpoints/listCertificates.json');
$mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock();
$mock->method('get')->willReturn($response);
$mock->expects($this->once())
->method('get')
->with(
$this->equalTo('certificates'),
$this->equalTo(
[
'zone_id' => '023e105f4ecef8ad9ca31a8372d0c353',
]
)
);
$certEndpoint = new Certificates($mock);
$result = $certEndpoint->listCertificates('023e105f4ecef8ad9ca31a8372d0c353');
$this->assertObjectHasAttribute('result', $result);
$cert = $result->result[0];
$this->assertEquals('328578533902268680212849205732770752308931942346', $cert->id);
$this->assertEquals('origin-rsa', $cert->request_type);
$this->assertEquals(5475, $cert->requested_validity);
$this->assertEquals(['example.com', '*.example.com'], $cert->hostnames);
$this->assertEquals('some-cert-data', $cert->certificate);
$this->assertEquals('some-csr-data', $cert->csr);
}
public function testGetCertificate()
{
$response = $this->getPsr7JsonResponseForFixture('Endpoints/getCertificate.json');
$mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock();
$mock->method('get')->willReturn($response);
$mock->expects($this->once())
->method('get')
->with(
$this->equalTo('certificates/6666699999996666699999999966666666'),
$this->equalTo(['zone_id' => '023e105f4ecef8ad9ca31a8372d0c353']),
$this->equalTo([])
);
$certEndpoint = new Certificates($mock);
$response = $certEndpoint->getCertificate(
'6666699999996666699999999966666666',
'023e105f4ecef8ad9ca31a8372d0c353'
);
$this->assertObjectHasAttribute('result', $response);
$cert = $response->result;
$this->assertEquals('6666699999996666699999999966666666', $cert->id);
$this->assertEquals('origin-ecc', $cert->request_type);
$this->assertEquals(5475, $cert->requested_validity);
$this->assertEquals(['foo.example.com', 'bar.example.com'], $cert->hostnames);
$this->assertEquals('some-cert-data-foobar', $cert->certificate);
$this->assertEquals('some-csr-data-foobar', $cert->csr);
}
public function testRevokeCertificate()
{
$response = $this->getPsr7JsonResponseForFixture('Endpoints/getCertificate.json');
$mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock();
$mock->method('delete')->willReturn($response);
$mock->expects($this->once())
->method('delete')
->with(
$this->equalTo('certificates/11112222233333444455555'),
$this->equalTo(['zone_id' => '023e105f4ecef8ad9ca31a8372d0c353']),
$this->equalTo([])
);
$certEndpoint = new Certificates($mock);
$result = $certEndpoint->revokeCertificate(
'11112222233333444455555',
'023e105f4ecef8ad9ca31a8372d0c353'
);
$this->assertTrue($result);
}
public function testCreateCertificate()
{
$certificate = new \Cloudflare\API\Configurations\Certificate();
$certificate->setHostnames(['foo.example.com', 'bar.exapmle.com']);
$certificate->setRequestType(\Cloudflare\API\Configurations\Certificate::ORIGIN_ECC);
$certificate->setRequestedValidity(365);
$certificate->setCsr('some-csr-data-barbar');
$response = $this->getPsr7JsonResponseForFixture('Endpoints/getCertificate.json');
$mock = $this->getMockBuilder(\Cloudflare\API\Adapter\Adapter::class)->getMock();
$mock->method('post')->willReturn($response);
$mock->expects($this->once())
->method('post')
->with(
$this->equalTo('certificates'),
$this->equalTo($certificate->getArray()),
$this->equalTo([])
);
$certEndpoint = new Certificates($mock);
$result = $certEndpoint->createCertificate($certificate);
$this->assertTrue($result);
}
}

View File

@@ -0,0 +1,17 @@
{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "12341234123412341234",
"certificate": "some-cert-data-foofoo",
"hostnames": [
"foo.example.com",
"bar.example.com"
],
"expires_on": "2014-01-01T05:20:00.12345Z",
"request_type": "origin-ecc",
"requested_validity": 365,
"csr": "some-csr-data-barbar"
}
}

View File

@@ -0,0 +1,17 @@
{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "6666699999996666699999999966666666",
"certificate": "some-cert-data-foobar",
"hostnames": [
"foo.example.com",
"bar.example.com"
],
"expires_on": "2014-01-01T05:20:00.12345Z",
"request_type": "origin-ecc",
"requested_validity": 5475,
"csr": "some-csr-data-foobar"
}
}

View File

@@ -0,0 +1,19 @@
{
"success": true,
"errors": [],
"messages": [],
"result": [
{
"id": "328578533902268680212849205732770752308931942346",
"certificate": "some-cert-data",
"hostnames": [
"example.com",
"*.example.com"
],
"expires_on": "2014-01-01T05:20:00.12345Z",
"request_type": "origin-rsa",
"requested_validity": 5475,
"csr": "some-csr-data"
}
]
}

View File

@@ -0,0 +1,8 @@
{
"success": true,
"errors": [],
"messages": [],
"result": {
"id": "11112222233333444455555"
}
}