-
Notifications
You must be signed in to change notification settings - Fork 1
对比本项目与 RFC 8555 出入的地方 #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: rfc8555
Are you sure you want to change the base?
Changes from 11 commits
8bae348
9eeb20a
62d9b1b
83e47d3
c08bb1f
ca5a355
9b572c9
2e5997a
85778e1
5a63b88
e75810e
24491ec
9712e7e
9bb6dd4
126ebb8
9fe2f20
51ce2fb
297ee09
d865632
d522db7
0c6088d
d550946
7ac8673
1675a73
50bf15f
26b54bb
a28ba03
d9e446f
898534d
bbdc836
97e512c
eb425e6
d84a112
6d113ee
985d918
6c79690
040b5b5
856526d
62a5bd4
d8ca2dc
1e07b36
5cad995
8541342
05a2f39
40558ea
67b8285
1a17f6e
1e9c675
723de09
2d88030
e9fefc3
91049e3
0d522f7
d20150c
505d4c2
0501e56
2400302
3292b41
c2c4720
634ef1b
6d17d7b
8684a94
bce7829
dcd1ad7
2a51a4d
dd40a03
45037e1
ce4bb92
9203dec
51da67e
22b674d
c329846
6928dbf
d39d70d
35ab635
a22f393
92ecf29
bddfd66
7710420
5dfef21
5781c34
88201a0
6a09ffb
4c6cc3c
aaf359b
8e82526
6ec120e
4c3ce4c
222f184
d060f0c
6eacee7
6446d96
b1a556a
1e7bbc1
58db1ba
697a6ec
ce40366
fe49856
144c49b
5307d84
2e6f3ca
8137324
e341ca7
4c5c90c
8b1597c
79cd99a
ce561b0
fe15f15
dcf3aeb
06dcff7
00dd962
6b65f1a
2c0dfc8
44a6aee
e6ea8f4
bdc1e9e
8e17037
11a6568
1c3c80e
5f47ad7
51ed68d
5eaa471
e22baa9
b320d72
ea0a21c
c43a234
d57efaa
9e01503
2ff71f7
6c390f6
ae3cda1
017a920
ca888f0
d752b16
bb20317
9fd2220
548b609
4af7fd1
7c2a9ff
5a2d100
d21c37b
2e1e108
a21445e
21535ff
f139c30
b8ae9eb
2959ec1
3628106
fee5ef2
324406c
61ac41d
77b6f5b
2d8b8ec
c6a7bb4
6ad71ba
f0e9422
0d09084
dbc895b
c592b85
937a2f7
25a12e3
028470a
ec1bbba
b86d2d6
df8f156
24b8575
d031223
b796512
c5de9ad
edb3d26
2a59ecc
a9ea89c
0ba4c4d
486dbb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,12 +19,21 @@ | |
| use Symfony\Component\Console\Input\InputInterface; | ||
| use Symfony\Component\Console\Input\InputOption; | ||
| use Symfony\Component\Console\Output\OutputInterface; | ||
| use AcmePhp\Cli\Command\Helper\KeyOptionCommandTrait; | ||
| use AcmePhp\Ssl\CertificateRequest; | ||
|
|
||
| /** | ||
| * @author Titouan Galopin <galopintitouan@gmail.com> | ||
| */ | ||
| class AuthorizeCommand extends AbstractCommand | ||
| { | ||
| use KeyOptionCommandTrait; | ||
|
|
||
| /** | ||
| * @var RepositoryInterface | ||
| */ | ||
| private $repository; | ||
|
|
||
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
|
|
@@ -34,6 +43,14 @@ protected function configure() | |
| ->setDefinition([ | ||
| new InputOption('solver', 's', InputOption::VALUE_REQUIRED, 'The type of challenge solver to use (available: http, dns, route53)', 'http'), | ||
| new InputArgument('domains', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'List of domains to ask an authorization for'), | ||
| new InputOption('country', null, InputOption::VALUE_REQUIRED, 'Your country two-letters code (field "C" of the distinguished name, for instance: "US")'), | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 因为 |
||
| new InputOption('province', null, InputOption::VALUE_REQUIRED, 'Your country province (field "ST" of the distinguished name, for instance: "California")'), | ||
| new InputOption('locality', null, InputOption::VALUE_REQUIRED, 'Your locality (field "L" of the distinguished name, for instance: "Mountain View")'), | ||
| new InputOption('organization', null, InputOption::VALUE_REQUIRED, 'Your organization/company (field "O" of the distinguished name, for instance: "Acme PHP")'), | ||
| new InputOption('unit', null, InputOption::VALUE_REQUIRED, 'Your unit/department in your organization (field "OU" of the distinguished name, for instance: "Sales")'), | ||
| new InputOption('email', null, InputOption::VALUE_REQUIRED, 'Your e-mail address (field "E" of the distinguished name)'), | ||
| new InputOption('alternative-name', 'a', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Alternative domains for this certificate'), | ||
| new InputOption('key-type', 'k', InputOption::VALUE_REQUIRED, 'The type of private key used to sign certificates (one of RSA, EC)', 'RSA'), | ||
| ]) | ||
| ->setDescription('Ask the ACME server for an authorization token to check you are the owner of a domain') | ||
| ->setHelp(<<<'EOF' | ||
|
|
@@ -56,8 +73,11 @@ protected function configure() | |
| */ | ||
| protected function execute(InputInterface $input, OutputInterface $output) | ||
| { | ||
| $this->repository = $this->getRepository(); | ||
|
|
||
| $client = $this->getClient(); | ||
| $domains = $input->getArgument('domains'); | ||
| $keyType = $input->getOption('key-type'); | ||
|
|
||
| $solverName = strtolower($input->getOption('solver')); | ||
|
|
||
|
|
@@ -68,8 +88,37 @@ protected function execute(InputInterface $input, OutputInterface $output) | |
| $solver = $solverLocator->get($solverName); | ||
| $this->debug('Solver found', ['name' => $solverName]); | ||
|
|
||
| $alternativeNames = $domains; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 生成 CSR 的逻辑. 初始化订单时候一起提交 |
||
| $domain = $alternativeNames[0]; | ||
| sort($alternativeNames); | ||
|
|
||
| $introduction = <<<'EOF' | ||
|
|
||
| There is currently no certificate for domain %s in the Acme PHP storage. As it is the | ||
| first time you request a certificate for this domain, some configuration is required. | ||
|
|
||
| <info>Generating domain key pair...</info> | ||
| EOF; | ||
|
|
||
| $this->info(sprintf($introduction, $domain)); | ||
|
|
||
| /* @var KeyPair $domainKeyPair */ | ||
| $domainKeyPair = $this->getContainer()->get('ssl.key_pair_generator')->generateKeyPair( | ||
| $this->createKeyOption($keyType) | ||
| ); | ||
| $this->repository->storeDomainKeyPair($domain, $domainKeyPair); | ||
|
|
||
| $this->debug('Domain key pair generated and stored', [ | ||
| 'domain' => $domain, | ||
| 'public_key' => $domainKeyPair->getPublicKey()->getPEM(), | ||
| ]); | ||
| $distinguishedName = $this->getOrCreateDistinguishedName($domain, $alternativeNames); | ||
| $this->notice('Distinguished name informations have been stored locally for this domain (they won\'t be asked on renewal).'); | ||
| $this->notice(sprintf('Loading the order related to the domains %s ...', implode(', ', $domains))); | ||
| $csr = new CertificateRequest($distinguishedName, $domainKeyPair); | ||
|
|
||
| $this->notice(sprintf('Requesting an authorization token for domains %s ...', implode(', ', $domains))); | ||
| $order = $client->requestOrder($domains); | ||
| $order = $client->requestOrder($domains, $csr); | ||
| $this->notice('The authorization tokens was successfully fetched!'); | ||
| $authorizationChallengesToSolve = []; | ||
| foreach ($order->getAuthorizationsChallenges() as $domainKey => $authorizationChallenges) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -342,60 +342,4 @@ private function executeRenewal($domain, array $alternativeNames) | |
| throw $e; | ||
| } | ||
| } | ||
|
|
||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 挪到 Trait 和 initializeOrder 方法共用 |
||
| /** | ||
| * Retrieve the stored distinguishedName or create a new one if needed. | ||
| * | ||
| * @param string $domain | ||
| * @param array $alternativeNames | ||
| * | ||
| * @return DistinguishedName | ||
| */ | ||
| private function getOrCreateDistinguishedName($domain, array $alternativeNames) | ||
| { | ||
| if ($this->repository->hasDomainDistinguishedName($domain)) { | ||
| $original = $this->repository->loadDomainDistinguishedName($domain); | ||
|
|
||
| $distinguishedName = new DistinguishedName( | ||
| $domain, | ||
| $this->input->getOption('country') ?: $original->getCountryName(), | ||
| $this->input->getOption('province') ?: $original->getStateOrProvinceName(), | ||
| $this->input->getOption('locality') ?: $original->getLocalityName(), | ||
| $this->input->getOption('organization') ?: $original->getOrganizationName(), | ||
| $this->input->getOption('unit') ?: $original->getOrganizationalUnitName(), | ||
| $this->input->getOption('email') ?: $original->getEmailAddress(), | ||
| $alternativeNames | ||
| ); | ||
| } else { | ||
| // Ask DistinguishedName | ||
| $distinguishedName = new DistinguishedName( | ||
| $domain, | ||
| $this->input->getOption('country'), | ||
| $this->input->getOption('province'), | ||
| $this->input->getOption('locality'), | ||
| $this->input->getOption('organization'), | ||
| $this->input->getOption('unit'), | ||
| $this->input->getOption('email'), | ||
| $alternativeNames | ||
| ); | ||
|
|
||
| /** @var DistinguishedNameHelper $helper */ | ||
| $helper = $this->getHelper('distinguished_name'); | ||
|
|
||
| if (!$helper->isReadyForRequest($distinguishedName)) { | ||
| $this->info("\n\nSome informations about you or your company are required for the certificate:\n"); | ||
|
|
||
| $distinguishedName = $helper->ask( | ||
| $this->getHelper('question'), | ||
| $this->input, | ||
| $this->output, | ||
| $distinguishedName | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| $this->repository->storeDomainDistinguishedName($domain, $distinguishedName); | ||
|
|
||
| return $distinguishedName; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,7 +96,7 @@ protected function execute(InputInterface $input, OutputInterface $output) | |
| $certificate | ||
| ); | ||
| } else { | ||
| $order = $this->challengeDomains($domainConfig); | ||
| $order = $this->challengeDomains($domainConfig, $keyOption); | ||
| $response = $this->requestCertificate($order, $domainConfig, $keyOption); | ||
| } | ||
|
|
||
|
|
@@ -228,7 +228,7 @@ private function requestCertificate(CertificateOrder $order, $domainConfig, KeyO | |
| return $response; | ||
| } | ||
|
|
||
| private function challengeDomains(array $domainConfig) | ||
| private function challengeDomains(array $domainConfig, KeyOption $keyOption) | ||
| { | ||
| $solverConfig = $domainConfig['solver']; | ||
| $domain = $domainConfig['domain']; | ||
|
|
@@ -246,8 +246,36 @@ private function challengeDomains(array $domainConfig) | |
| $client = $this->getClient(); | ||
| $domains = array_unique(array_merge([$domain], $domainConfig['subject_alternative_names'])); | ||
|
|
||
|
|
||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 生成 CSR |
||
| $domain = $domainConfig['domain']; | ||
| $this->output->writeln(sprintf('<comment>Requesting certificate for domain %s...</comment>', $domain)); | ||
|
|
||
| $repository = $this->getRepository(); | ||
| $client = $this->getClient(); | ||
| $distinguishedName = new DistinguishedName( | ||
| $domainConfig['domain'], | ||
| $domainConfig['distinguished_name']['country'], | ||
| $domainConfig['distinguished_name']['state'], | ||
| $domainConfig['distinguished_name']['locality'], | ||
| $domainConfig['distinguished_name']['organization_name'], | ||
| $domainConfig['distinguished_name']['organization_unit_name'], | ||
| $domainConfig['distinguished_name']['email_address'], | ||
| $domainConfig['subject_alternative_names'] | ||
| ); | ||
|
|
||
| if ($repository->hasDomainKeyPair($domain)) { | ||
| $domainKeyPair = $repository->loadDomainKeyPair($domain); | ||
| } else { | ||
| $domainKeyPair = $this->getContainer()->get('ssl.key_pair_generator')->generateKeyPair($keyOption); | ||
| $repository->storeDomainKeyPair($domain, $domainKeyPair); | ||
| } | ||
|
|
||
| $repository->storeDomainDistinguishedName($domain, $distinguishedName); | ||
|
|
||
| $csr = new CertificateRequest($distinguishedName, $domainKeyPair); | ||
|
|
||
| $this->output->writeln('<comment>Requesting certificate order...</comment>'); | ||
| $order = $client->requestOrder($domains); | ||
| $order = $client->requestOrder($domains, $csr); | ||
|
|
||
| $authorizationChallengesToSolve = []; | ||
| foreach ($order->getAuthorizationsChallenges() as $domain => $authorizationChallenges) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -131,10 +131,15 @@ public function requestAuthorization($domain) | |
| /** | ||
| * {@inheritdoc} | ||
| */ | ||
| public function requestOrder(array $domains) | ||
| public function requestOrder(array $domains, $csr = null) | ||
| { | ||
| Assert::allStringNotEmpty($domains, 'requestOrder::$domains expected a list of strings. Got: %s'); | ||
|
|
||
| $humanText = ['-----BEGIN CERTIFICATE REQUEST-----', '-----END CERTIFICATE REQUEST-----']; | ||
|
||
| $csrContent = $this->csrSigner->signCertificateRequest($csr); | ||
| $csrContent = trim(str_replace($humanText, '', $csrContent)); | ||
| $csrContent = trim($this->getHttpClient()->getBase64Encoder()->encode(base64_decode($csrContent))); | ||
|
|
||
| $payload = [ | ||
| 'identifiers' => array_map( | ||
| function ($domain) { | ||
|
|
@@ -145,6 +150,7 @@ function ($domain) { | |
| }, | ||
| array_values($domains) | ||
| ), | ||
| 'csr' => $csrContent, | ||
| ]; | ||
|
|
||
| $response = $this->getHttpClient()->signedKidRequest('POST', $this->getResourceUrl(ResourcesDirectory::NEW_ORDER), $this->getResourceAccount(), $payload); | ||
|
|
@@ -360,7 +366,10 @@ private function createAuthorizationChallenge($domain, array $response) | |
| $response['type'], | ||
| $response['url'], | ||
| $response['token'], | ||
| $response['token'].'.'.$base64encoder->encode($this->getHttpClient()->getJWKThumbprint()) | ||
| isset($response['filecontent']) ? $response['filecontent'] : ($response['token'].'.'.$base64encoder->encode($this->getHttpClient()->getJWKThumbprint())), | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 因为 trustocean (comodoca) 的验证路径/文件名/内容不一致. 特意加上的补充参数 |
||
| isset($response['path']) ? $response['path'] : null, | ||
| isset($response['verifyurl']) ? $response['verifyurl'] : null, | ||
| isset($response['filecontent']) ? $response['filecontent'] : null | ||
| ); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,7 +46,7 @@ public function getCheckUrl(AuthorizationChallenge $authorizationChallenge) | |
| public function getCheckPath(AuthorizationChallenge $authorizationChallenge) | ||
| { | ||
| return sprintf( | ||
| '/.well-known/acme-challenge/%s', | ||
| $authorizationChallenge->getPath() ? ($authorizationChallenge->getPath() . '%s') : '/.well-known/acme-challenge/%s', | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| $authorizationChallenge->getToken() | ||
| ); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ public function write($path, $content) | |
|
|
||
| public function delete($path) | ||
| { | ||
| return; | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. keep un-deleted. because when program run here, comodo is not verified for certain yet. |
||
| $isOnRemote = $this->filesystem->has($path); | ||
| if ($isOnRemote && !$this->filesystem->delete($path)) { | ||
| throw $this->createRuntimeException($path, 'delete'); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
因为
csrEager需要生成 KEY