Um dos aspectos mais excitantes da computação em nuvem é a capacidade de executar máquinas virtuais em um datacenter do provedor em nuvem. O EC2 da Amazon proporciona a arquitetos e desenvolvedores a capacidade de criar imagens de máquinas virtuais e executá-las na nuvem. É possível criar imagens customizadas que contêm o software e os dados que sua organização precisa, então será possível executar quantas cópias dessas máquinas virtuais forem necessárias. Este artigo aborda algumas das classes no Zend Framework que tornam mais fácil trabalhar com imagens EC2.
Como o EC2 é um produto sofisticado, os recursos do EC2 são divididos em dois artigos. Este artigo aborda os conceitos básicos do trabalho com imagens, início e término das instâncias dessas imagens e os pares de chaves e grupos de segurança que permitem proteger as instâncias. Tópicos como Endereços IP Elásticos, Monitoramento do Amazon CloudWatch e Armazenamento em Bloco Elástico são abordados em um outro artigo.
Neste artigo, você verá como realizar várias tarefas importantes do EC2:
- Localizar as Amazon Machine Images (AMIs) que pertencem a você
- Trabalhar com pares de chaves, incluindo localizar aqueles que pertencem a você, criar novos e excluir antigos
- Trabalhar com grupos de segurança, incluindo controle de acesso às portas TCP/IP de sua máquina virtual
- Iniciar uma instância de uma AMI
- Reinicializar ou terminar uma instância de uma AMI
Como com todos os artigos nesta série, você aproveitará o máximo dos exemplos
se você tiver o Zend Framework instalado antes de iniciar. Se não tiver
o Zend Framework instalado ainda, faça o download e instale o pacote
completo a partir de
zend.com/community/downloads.
Esse pacote instala o Zend Framework, o PHP e o servidor da Web Apache
em sua máquina. Quando a instalação for concluída, acesse
http://localhost/ZendServer/ em seu navegador.
Consulte a documentação de instalação do Zend Framework para obter todos os detalhes. Se
você conseguir efetuar login no console do ZendServer, tudo estará configurado.
Também será necessário configurar uma conta com a Amazon (consulte Recursos).
Os exemplos usam a classe Credentials do PHP criada na Parte 1. Essa classe gerencia as credenciais para sua conta Amazon. As credenciais são armazenadas em um arquivo .ini.
Lista 1. Armazenando credenciais em um arquivo .ini do PHP
,
; Arquivos de configuração para conter chaves secretas,
números de contas e outras cadeias úteis para a Amazon e outras contas de nuvem.
[amazon]
accessKey=0123456789ABCDEFGHIJ
secretKey=0123456789abcdefghiABCDEFGHI1234567890AB
ownerId=123456789012
|
Neste artigo, o valor ownerId é essencial.
Há milhares de AMIs disponíveis na Amazon, a maioria das quais não estão
disponíveis para o público em geral.
Você usará o valor ownerId
para filtrar as AMIs nas quais você não possui
autorização para acesso. Seu ID de proprietário é o número de 12 dígitos
de sua conta no Amazon Web Services. Para localizá-lo, acesse
http://aws.amazon.com/, efetue login em sua conta e,
em seguida, selecione o menu Your Account e o item Security Credentials
.
Figura 1. Localizando suas credenciais de segurança
Role para baixo até o meio da página e verá o ID de sua conta AWS.
Figura 2. ID de sua conta no AWS
Ao colocar o ID de sua conta no arquivo cloud.ini,
não use os hifens. Se este fosse seu ID, você incluiria
ownerId=999999999999 no
arquivo .ini.
Notas:
- Sempre que iniciar uma instância de uma AMI, você está gastando dinheiro. Mesmo que as taxas do EC2 sejam razoáveis (algumas instâncias custam menos de 10 centavos de dólar americano por hora), você não desejará simplesmente iniciar uma AMI e deixá-la em execução por tempo indeterminado. Certifique-se de terminar suas instâncias quando não for usá-las mais.
- Os exemplos neste artigo assumem que você criou pelo menos uma AMI.
Se não criou, poderá usar o valor especial
ownerId=amazon. Isso retornará uma lista de mais de 100 AMIs, mas fornecerá algumas imagens que você pode ativar. - Se estiver usando
ownerId=amazon, esteja ciente de que algumas dessas instâncias podem ser bastante caras. A IBM® possui várias AMIs que apresentam produtos de software de classe corporativa. Se estiver usando uma dessas AMIs, estará pagando uma taxa de licenciamento enquanto a instância estiver em execução. Se tudo o que deseja fazer é experimentar trabalhar com o EC2, uma AMI resumida em recursos provavelmente possui um baixo custo.
O aplicativo de amostra consiste em seis páginas de código em PHP:
amis.php— Lista todas as AMIs de sua conta. É possível iniciar uma instância de qualquer AMI apenas clicando em um botão.manage_instance.php— Manipual pedidos a partir doamis.phppara criar, reinicializar e terminar uma instância de uma AMI.instances.php— Lista todas as instâncias em execução controladas por sua conta. Reinicialize ou termine qualquer instância em execução apenas clicando em um botão.keypairs.php— Lista todos os pares de chaves públicas/privadas que você criou. Examine pares de chaves existentes, crie novos e exclua os existentes.securitygroups.php— Lista todos os grupos de segurança definidos para sua conta. Clique em um botão para ver os detalhes de um determinado grupo de segurança.securitygroup.php— Lista todas as permissões para um determinado grupo de segurança. Inclua novas permissões ou exclua as existentes.
Para começar, crie um objeto
Zend_Service_Amazon_Ec2_Image .
Lista 2. Criando um objeto
Zend_Service_Amazon_Ec2_Image ,
; Configuration file to hold secret keys, account numbers and other useful
; strings for Amazon and other cloud accounts.
[amazon]
accessKey=0123456789ABCDEFGHIJ
secretKey=0123456789abcdefghiABCDEFGHI1234567890AB
ownerId=123456789012
|
Este objeto permite trabalhar com as AMIs armazenadas na Amazon. O método
Zend_Service_Amazon_Ec2_Image->describe()
retorna os metadados sobre uma AMI. Sem argumentos, ele retorna os
detalhes de todas as AMIs armazenadas na Amazon. Isso gera uma grande
quantidade de dados, a maioria dos quais não é útil para você. Infelizmente,
a atual representação do Zend Framework não suporta a versão de
describe() que permite especificar um
ownerId. Isso significa que a primeira vez
que desejar listar as AMIs relevantes para o usuário, precisará classificar
toda a lista para localizar as AMIs que deseja. Para contornar isso, é possível
armazenar em cache os IDs das AMIs que deseja exibir. A lógica de processamento
é que, se existe um arquivo listando as AMIs relevantes, você simplesmente lê
esse arquivo e chama describe('ami-id') para cada ID.
Se o arquivo não existe, será necessário criá-lo; o arquivo PHP também fornece
ao usuário a opção de atualizar a lista de AMIs se ele desejar. Isso demorará
um pouco, mas garantirá que a lista esteja consistente com os dados na
Amazon.
O código para criar a lista de AMIs é semelhante à Lista 3.
Lista 3. Armazenando em cache os IDs de AMIs
,
if (!file_exists('amis.text') ||
array_key_exists('refresh', $_POST)) {
$imageData = $ec2_img->describe();
$amiFile = fopen('amis.text', 'w');
$myOwnerId = $creds->getCredential('amazon', 'ownerId');
foreach ($imageData as $nextImage) {
if ($nextImage['imageOwnerId'] === $myOwnerId)
fwrite($amiFile, $nextImage['imageId']."\n");
}
fclose($amiFile);
}
|
O código aqui verifica se ele precisa classificar todas as AMIs no catálogo da Amazon. Se o arquivo não existe ou há um pedido explícito para atualizá-lo, o código obtém a lista de detalhes de todas as AMIs na Amazon. O objetivo aqui é criar uma tabela de AMIs.
Figura 3. Uma lista de AMIs
Cada linha na tabela apresenta o ID da AMI, sua localização, seu status e
sua plataforma. Além disso, há duas listas suspensas que permitem a
escolha de um par de chaves e um grupo de segurança. A coluna final
na tabela é um botão de pressionamento que permite iniciar a AMI com o
par de chaves e o grupo de segurança atualmente selecionados. Para criar a tabela,
use o método file() do PHP para ler a lista de AMIs
em uma array. Para cada item na array, crie uma linha de tabela que conterá
todas as informações relevantes. A seguir, o código que cria as linhas
da tabela.
Lista 4. Gerando as linhas da tabela de AMIs
,
$amiList = file('amis.text', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach ($amiList as $nextAmi) {
echo "<tr>";
// Each table row is a form. Clicking the 'Start this image' button submits
// the data from the current row, which tells instances.php which image to
// start and which key pair and security group to use.
echo "<form action='manage_instance.php' method='POST' ";
echo " onsubmit='return confirm(\"Start image '".$nextAmi."'?\")'>";
echo "<input type='hidden' name='imagetostart' value='".$nextAmi."'/>";
echo "<td>".$nextAmi."</td>";
// Get the description of this AMI
$imageData = $ec2_img->describe(array('imageId' => $nextAmi));
echo "<td>".$imageData[0]['imageLocation']."</td>";
echo "<td>".$imageData[0]['imageState']."</td>";
// If the platform is blank, assume it's some flavor of Linux
if (strlen($imageData[0]['platform']))
echo "<td>".$imageData[0]['platform']."</td>";
else
echo "<td>Linux</td>";
// Insert the lists of key pairs and security groups
echo "<td>".$keypairsForm."</td>";
echo "<td>".$secGroupsForm."</td>";
// If the state of the image is "available," insert a start button.
if ($imageData[0]['imageState'] == 'available')
echo "<td><input type='submit' value='Start this image'/></td>";
else
echo "<td>Not available</td>";
echo "</form>";
echo "</tr>";
}
|
Cada linha da tabela deve estar em um elemento
<form> separado para que o navegador
saiba qual par de chaves e grupo de segurança está selecionado quando o botão Start for
clicado. Conforme você itera por meio da array de IDs de AMIs, chamar
describe() com um ID específico retorna a
descrição dessa AMI em particular. O restante da linha de tabela consiste no
local da imagem (onde a imagem é armazenada em sua conta S3),
o status da imagem, uma lista suspensa de pares de chaves, uma lista suspensa
de grupos de segurança e um botão Start this image . O botão Start é exibido
apenas se o status da imagem for
available. Os controles de formulário para cada linha
da tabela se parecem com a Figura 4.
Figura 4. Controles de formulário para cada linha da tabela
As listas de pares de chaves e grupos de segurança são criados fora do loop.
Lista 4. Gerando as listas de pares de chaves e grupos de segurança
,
$ec2_kp = new Zend_Service_Amazon_Ec2_Keypair($aws_key, $aws_secret);
$keypairs = $ec2_kp->describe();
foreach ($keypairs as $key => $row) {
$keyName[$key] = $row['keyName'];
$keyFingerprint[$key] = $row['keyFingerprint'];
}
array_multisort($keyName, $keypairs);
$keypairsList = "<select name='keypair'>";
foreach ($keypairs as $nextKeypair) {
$keypairsList = $keypairsList."<option value='".$nextKeypair['keyName']."'>";
$keypairsList = $keypairsList.$nextKeypair['keyName']."</option>";
}
$keypairsList = $keypairsList."</select>";
$secGroupsList = "<select name='secgroup'>";
$ec2_sg = new Zend_Service_Amazon_Ec2_Securitygroups($aws_key, $aws_secret);
$securityGroups = $ec2_sg->describe();
foreach ($securityGroups as $key => $row) {
$groupName[$key] = $row['groupName'];
$groupDescription[$key] = $row['groupDescription'];
}
array_multisort($groupName, $securityGroups);
foreach ($securityGroups as $nextGroup) {
$secGroupsList = $secGroupsList."<option value='".$nextGroup['groupName']."'>";
$secGroupsList = $secGroupsList.$nextGroup['groupName']."</option>";
}
$secGroupsList = $secGroupsList."</select>";
|
Cada lista é uma cadeia que contém os elementos
<select> e
<option> do HTML para os pares
de chaves e grupos de segurança. (Observe que o código usa o
array_multisort do PHP para classificar os nomes dos
pares de chaves e grupos de segurança.) Como o início de uma instância de uma AMI
significa que encargos começam a acumular em sua conta no AWS, um diálogo de confirmação é exibido.
Figura 5. O início de uma instância deve ser confirmado
Nesta captura de tela, o par de chaves
id_rsa-gsg-keypair e o grupo de segurança
default estão selecionados.
Ao clicar no botão OK para ativar uma instância, as informações sobre
a nova instância são enviadas para a página
manage_instance.php . A primeira etapa ao trabalhar
com instâncias é criar um objeto
Zend_Service_Amazon_Ec2_Instance .
Lista 6. Criando um objeto Zend_Service_Amazon_Ec2_Instance
,
$creds = new Credentials;
$aws_key = $creds->getCredential('amazon', 'accessKey');
$aws_secret = $creds->getCredential('amazon', 'secretKey');
$ec2_instance = new Zend_Service_Amazon_Ec2_Instance($aws_key, $aws_secret);
|
Com o objeto criado, agora é possível iniciar uma instância da imagem solicitada.
Lista 7. Criando uma nova instância
,
if (strlen($imageIdToStart) && strlen($keypairToStart) && strlen($secgroupToStart)) {
$startResults = $ec2_instance->run(array('imageId' => $imageIdToStart,
'keyName' => $keypairToStart,
'securityGroup' => $secgroupToStart));
echo "<p><b>Status of instance ".$startResults['instances'][0]['instanceId'].": ";
echo $startResults['instances'][0]['instanceState']['name'].".</b></p><hr/>";
}
|
Observação: É possível especificar outros parâmetros ao iniciar uma instância,
como o número de instâncias, o tamanho da instância (quanta memória e processamento
de CPU ela possui) e a região geográfica em que a instância deverá estar
hospedada. Para manter os exemplos simples, todas as solicitações de início de uma instância
apenas iniciam uma instância, essa instância possui o menor tamanho (especificado como
m1.small no pedido real para a Amazon) e é hospedada
na região padrão para sua conta.
Este código assume o ID da AMI e os nomes do par de chaves e do
grupo de segurança selecionados no formulário na página
amis.php . Então, a página exibe o
status da nova instância.
Figura 6. O status de uma instância recém-criada
Ao clicar em OK será enviada a você a página instances.php .
Essa página exibe a lista atual de instâncias.
Figura 7. A lista de instâncias
Observação: Os valores para o ID de imagem, nome da chave e grupo de segurança
são passados para a página manage_instance.php via HTTP
POST. Usar uma página intermediária para criar a nova instância significa
que é possível atualizar a página instances.php sem iniciar acidentalmente
uma outra instância. A página
manage_instance.php também manipula pedidos
de reinicialização ou término de uma imagem.
Ao iniciar uma instância, seu estado inicial é
pending. Isso significa que a imagem da máquina
está inicializando, mas ainda não está ativada e em execução. Observe também que a Amazon designou
i-373c995f como ID de instância para esta
instância; esse ID é como você trabalhará com a instância posteriormente. Clicar no
botão "Refresh list of instances" atualiza a exibição.
Figura 8. Atualizar lista de instâncias
Na lista atualizada, o status da instância agora é
running. Observe que a Amazon
designou o nome de DNS
ec2-75-101-220-48.compute-1.amazonaws.com para
esta instância. Isso significa que, se você habilitou esta instância para
acesso pela Web e a instância está executando um servidor da Web na porta
80, será possível visitar
http://ec2-75-101-220-48.compute-1.amazonaws.com
para ver a página inicial da instância. (É possível ativar a porta 80 criando
uma regra em um grupo de segurança; mais sobre grupos de segurança em breve.)
Para gerar as linhas da tabela de instâncias, use o método
Zend_Service_Amazon_Ec2_Instance->describe()
.
Lista 8. Criando a tabela de instâncias
,
$instanceDetails = $ec2_instance->describe();
if (count($instanceDetails['instances'])) {
echo "<table border='1' cellpadding='5'>";
echo "<tr style='font-weight: bold;'>";
echo "<td>Status</td><td>Instance ID</td><td>AMI ID</td><td>Public DNS name</td>";
echo "<td>Security Group</td><td>Key Pair</td><td> </td><td> </td>";
echo "</tr>";
foreach ($instanceDetails['instances'] as $nextInstance) {
echo "<tr>";
$status = $nextInstance['instanceState']['name'];
// Make the cell background green if the status is running.
if (strripos('running', $status) === 0)
echo "<td style='background-color: green; color: white; font-weight: bold;'>";
// Make the cell background yellow if the status is shutting-down.
else if (strripos('shutting-down', $status) === 0)
echo "<td style='background-color: yellow; font-weight: bold;'>";
// Make the cell background red if the status is terminated.
else if (strripos('terminated', $status) === 0)
echo "<td style='background-color: red; color: white; font-weight: bold;'>";
// Make the cell background purple for any other status.
else
echo "<td style='background-color: purple; color: white; font-weight: bold;'>";
echo $status."</td>";
echo "<td>".$nextInstance['instanceId']."</td>";
echo "<td>".$nextInstance['imageId']."</td>";
echo "<td>".$nextInstance['dnsName']."</td>";
echo "<td><a href='securitygroup.php?groupname=".$nextInstance['groupSet'][0];
echo "&previous=instances'>".$nextInstance['groupSet'][0]."</a></td>";
echo "<td>".$nextInstance['keyName']."</td>";
. . .
|
Primeiro, o código verifica se há alguma instância. Assumindo que há pelo
menos uma, cada instância é descrita em uma linha da tabela. O ID da
instância e o ID da AMI são exibidos, juntamente com o nome de DNS público,
grupo de segurança e par de chaves. Como com a página
amis.php , cada linha da tabela é um
formulário.
Figura 9. Controles de formulário para gerenciar instâncias
Esta tabela lista três instâncias. O status de dois dos itens é
running, portanto, há botões Reboot e
Terminate para essas instâncias. Para uma instância em um outro estado
(pending,
shutting-down ou
terminated), os botões não aparecem.
Lista 9. Criando os controles de formulário para a tabela de instâncias
,
if (strripos('running', $status) === false) {
echo "<i>[Can't reboot]</i>";
}
else {
echo "<form action='manage_instance.php' method='POST' ";
echo "onsubmit='return confirm(\"Reboot instance '";
echo $nextInstance['instanceId']."'?\")'>";
echo "<input type='hidden' name='imagetoreboot' value='";
echo $nextInstance['instanceId']."'/>";
echo "<input type='submit' value='Reboot'/></form>";
}
echo "</td>";
echo "<td style='text-align: center;'>";
if (strripos('running', $status) === false) {
echo "<i>[Can't terminate]</i>";
}
else {
echo "<form action='manage_instance.php' method='POST' ";
echo "onsubmit='return confirm(\"Terminate instance '";
echo $nextInstance['instanceId']."'?\")'>";
echo "<input type='hidden' name='imagetoterminate' value='";
echo $nextInstance['instanceId']."'/>";
echo "<input type='submit' value='Terminate'/></form>";
}
echo "</td>";
|
Se a instância estiver em execução, o código criará botões para reinicializar ou terminar a instância. Clicar nesses botões gera um diálogo de confirmação.
Figura 10. O término ou reinicialização de uma instância deve ser confirmado
Clicar em OK leva você novamente para a página manage_instance.php
.
Figura 11. O status de uma instância recém-terminada
Ao retornar para a lista de instâncias, o status atualizado é mostrado.
Figura 12. A lista de instâncias atualizada
Em algum ponto, o status da instância será alterado para
terminated.
Figura 13. Uma instância terminada
Observação: Em algum ponto após o término de uma instância, o EC2 exclui todos os dados associados a ela. Geralmente, isso ocorre dentro de uma hora. Assim que os dados sobre a instância forem excluídos, eles não serão mais mostrados nos resultados.
Trabalhando com pares de chaves
Um par de chaves é um par de chaves públicas e privadas usadas para autenticar um usuário.
Ao iniciar uma instância, especifique um par de chaves que possa ser usado para
acessar a instância quando ela estiver ativada e em execução. A Amazon associa a chave pública
a essa instância. Dependendo de como a AMI estiver configurada, talvez não seja
possível acessar a instância sem a chave privada. O arquivo
keypairs.php exibe todos os pares de chaves
definidos para sua conta.
Figura 14. A lista de pares de chaves
Para cada par de chaves, a tabela exibe seu nome e impressão digital.
Lista 10. Criando a tabela de pares de chaves
,
$creds = new Credentials;
$ec2_kp = new Zend_Service_Amazon_Ec2_Keypair>
($creds->getCredential('amazon', 'accessKey'),
$creds->getCredential('amazon', 'secretKey'));
$keypairs = $ec2_kp->describe();
if (count($keypairs)) {
echo "<p>Here are the key pairs defined for your account:</p>";
echo "<table border='1' cellpadding='5'>";
echo "<tr style='font-weight: bold;'>";
echo "<td>Key Pair Name</td>";
echo "<td>Fingerprint</td>";
echo "<td> </td>";
echo "</tr>";
foreach ($keypairs as $key => $row) {
$keyName[$key] = $row['keyName'];
$keyFingerprint[$key] = $row['keyFingerprint'];
}
array_multisort($keyName, $keypairs);
foreach ($keypairs as $nextKeypair) {
echo "<tr>";
echo "<td> ".$nextKeypair['keyName']."</td>";
echo "<td> ".$nextKeypair['keyFingerprint']."</td>";
echo "<td>";
echo "<form action='".$_SERVER['PHP_SELF']."' method='post'";
echo " onsubmit='return confirm(\"Do you really want to delete the key pair ";
echo "'".$nextKeypair['keyName']."'?\");'>";
echo "<input type='hidden' name='keypairtodelete' ";
echo "value='".$nextKeypair['keyName']."'/>";
echo "<input type='submit' value='Delete'/>";
echo "</form>";
echo "</td>";
echo "</tr>";
}
echo "</table>";
}
else
echo "<p>Sorry, your account doesn't have any key pairs defined.</p>";
|
O código cria um objeto
Zend_Service_Amazon_Ec2_Keypair e, em seguida,
chama seu método describe() para obter os detalhes
de todos os pares de chaves definidos para sua conta. Para cada par de chaves, o AWS
retorna o nome do par de chaves e sua impressão digital. Cada linha da tabela
também contém um formulário HTML com um botão Excluir . O formulário requer
uma confirmação para qualquer pedido de exclusão.
Figura 15. A exclusão de um par de chaves deve ser confirmada
O método delete() torna direta a exclusão do
par de chaves.
Lista 11. Excluindo um par de chaves
,
if (strlen($keypairToDelete)) {
echo "<p><b>";
try {
$ec2_kp->delete($keypairToDelete);
echo "The key pair named ".$keypairToDelete." was deleted successfully.";
}
catch (Zend_Service_Amazon_Ec2_Exception $ec2e) {
echo "The key pair could not be deleted. The error message from Amazon is:";
echo "<br/><br/><i>".$ec2e->getMessage()."</i>";
}
echo "</b></p><hr/><br/>";
}
|
A página keypairs.php também contém um formulário
para criar um novo par de chaves. O único parâmetro é um nome para o novo par de chaves.
Figura 16. Formulário para criar um novo par de chaves
Criar um par de chaves é tão simples quanto chamar o método
create() .
Lista 12. Criando a tabela de regras no grupo de segurança
foreach ($list[0]['ipPermissions'] as $key => $row) {
$ipProtocol[$key] = $row['ipProtocol'];
$startingPort[$key] = $row['fromPort'];
$toPort[$key] = $row['toPort'];
$ipRanges[$key] = $row['ipRanges'];
}
array_multisort($startingPort, SORT_ASC, $list[0]['ipPermissions']);
foreach($list[0]['ipPermissions'] as $rule) {
. . .
echo "<tr>\n";
echo "<td> ".strtoupper($rule['ipProtocol'])."</td>\n";
echo "<td> ".$rule['fromPort']."</td>\n";
echo "<td> ".$rule['toPort']."</td>\n";
if ((is_array($rule['ipRanges']) && count($rule['ipRanges']) == 0) ||
(strlen($rule['ipRanges']) == 0)) {
echo "<td> ---</td>\n";
echo "<td> </td>\n";
}
else {
echo "<td> ".$rule['ipRanges']."</td>\n";
echo "<td style='text-align: center;'>";
echo "<form action='".$_SERVER['PHP_SELF']."' method='POST'";
echo " onsubmit='return confirm(\"Do you really want to revoke access for IP ";
echo " address range '".$rule['ipRanges']."' on this port?\");'>";
echo "<input type='hidden' name='groupname' value='".$groupName."'/>";
echo "<input type='hidden' name='fromport' value='".$rule['fromPort']."'/>";
echo "<input type='hidden' name='toport' value='".$rule['toPort']."'/>";
echo "<input type='hidden' name='iptorevoke' value='".$rule['ipRanges']."'/>";
echo "<input type='submit' value='Revoke'/></form></td>";
} |
A resposta da Amazon contém a chave privada para o novo par de chaves. A página PHP exibe essa informação com uma mensagem para o usuário.
Figura 17. Um par de chaves recém-criado
O usuário deve copiar e colar a informação de chave privada em um arquivo. Se esta informação for perdida, ela não poderá ser recriada. (A criação de uma solução mais elegante que grava automaticamente os dados do par de chaves em um arquivo é deixada como um exercício para o leitor.)
Trabalhando com grupos de segurança
O formulário que permite criar novas instâncias requer a especificação de uma imagem de máquina, um par de chaves e um grupo de segurança. Um grupo de segurança permite definir como outras máquinas poderão acessar uma instância. Por exemplo, se deseja usar uma instância em execução como um servidor da Web, você definiria uma regra em seu grupo de segurança que os pedidos de conexão na porta 80 devem ser aceitos a partir de qualquer máquina. Para cada regra, especifique um protocolo, um intervalo de portas e um intervalo de endereços IP autorizados a acessar essas portas por meio desse protocolo. A exibição de um grupo de segurança é semelhante à Figura 18.
Figura 18. Um grupo de segurança
Aqui, a tabela lista as políticas de segurança para o grupo de segurança
default. Na parte inferior da captura de tela,
é possível ver que a política permite que os hosts 67.93.2.12 e 76.182.90.9
acessem a porta 80. A porta 3389, geralmente usada para sessões do Desktop Remoto
com VMs Windows, também é autorizada para o endereço IP 76.182.90.9. É possível
especificar um intervalo de portas; neste exemplo, as regras para as portas 21, 22 e
23 poderiam ter sido definidas com uma única regra. Cada linha da tabela contém um
formulário para exclusão de uma regra individual. O código para criar a tabela
é relativamente direto.
Lista 13. Criando a tabela de regras no grupo de segurança
,
foreach ($list[0]['ipPermissions'] as $key => $row) {
$ipProtocol[$key] = $row['ipProtocol'];
$startingPort[$key] = $row['fromPort'];
$toPort[$key] = $row['toPort'];
$ipRanges[$key] = $row['ipRanges'];
}
array_multisort($startingPort, SORT_ASC, $list[0]['ipPermissions']);
foreach($list[0]['ipPermissions'] as $rule) {
. . .
echo "<tr>\n";
echo "<td> ".strtoupper($rule['ipProtocol'])."</td>\n";
echo "<td> ".$rule['fromPort']."</td>\n";
echo "<td> ".$rule['toPort']."</td>\n";
if ((is_array($rule['ipRanges']) && count($rule['ipRanges']) == 0) ||
(strlen($rule['ipRanges']) == 0)) {
echo "<td> ---</td>\n";
echo "<td> </td>\n";
}
else {
echo "<td> ".$rule['ipRanges']."</td>\n";
if (strripos('0.0.0.0', $rule['ipRanges'][0]) === false) {
echo "<td style='text-align: center;'>";
echo "<form action='".$_SERVER['PHP_SELF']."' method='POST'";
echo " onsubmit='return confirm(\"Do you really want to revoke access for IP ";
echo " address range '".$rule['ipRanges']."' on this port?\");'>";
echo "<input type='hidden' name='groupname' value='".$groupName."'/>";
echo "<input type='hidden' name='fromport' value='".$rule['fromPort']."'/>";
echo "<input type='hidden' name='toport' value='".$rule['toPort']."'/>";
echo "<input type='hidden' name='iptorevoke' value='".$rule['ipRanges']."'/>";
echo "<input type='submit' value='Revoke'/></form></td>";
}
else
echo "<td> </td>"; |
Antes de construir as linhas da tabela, o código usa a função
array_multisort para classificar a array de
regras pelo número da porta inicial de cada regra. A exibição do nome do
protocolo, da porta inicial e da porta final é direta. As duas últimas
colunas na tabela estão no intervalo de endereços IP e um botão para revogar
uma permissão. Em alguns casos, o intervalo de endereços IP é retornado como
uma array vazia ou uma cadeia vazia. Se esse for o caso, a tabela conterá uma célula
vazia em vez de um botão Revoke .
A última linha da tabela contém um formulário para criação de uma nova regra.
Figura 19. O formulário para criação de uma nova regra
A Amazon requer que o endereço IP seja especificado na nota Classless Inter-Domain Routing (CIDR). A nota CIDR é um endereço IP, seguido por uma barra e um número de 0 a 32. O número após a barra especifica quantos bits do endereço IP estão no prefixo. Por exemplo, a nota CIDR 9.67.0.0/16 corresponde a qualquer endereço que inicie com 9.67. O intervalo de IPs 0.0.0.0/0 corresponde a qualquer endereço IP, apesar do intervalo 76.182.90.9/32 corresponder apenas com o endereço IP 76.182.90.9. Se o usuário inserir um endereço IP que não está na nota CIDR, a página PHP incluirá /32 no endereço. (Consulte Recursos para aprender mais sobre CIDR.) O código para autorizar um intervalo de IPs é direto.
Lista 14. Autorizando um novo intervalo de endereços IP
,
if (strlen($ipToAuthorize) && strripos($ipToAuthorize, '/') === false)
$ipToAuthorize = $ipToAuthorize."/32";
. . .
try {
$ec2_sg->authorizeIp($groupName, $protocol, $fromPort, $toPort, $ipToAuthorize);
echo "IP address ".$ipToAuthorize." is now authorized.";
}
catch (Zend_Service_Amazon_Ec2_Exception $ec2e) {
// We get an exception if this IP address is already authorized, that's okay.
if ($ec2e->getErrorCode() == 'InvalidPermission.Duplicate')
echo "IP address range ".$ipToAuthorize." is already authorized.";
// If the IP address range isn't formatted correctly, tell the user.
else if ($ec2e->getErrorCode() == 'InvalidPermission.Malformed')
echo "The value ".$ipToAuthorize." is not a valid IP address range.";
// For all other exceptions, we just dump the exception to the screen.
else {
echo "<i>Something really bad happened:</i><br/><pre>";
var_dump($ec2e);
echo "</pre>";
}
}
|
Chamar o método authorizeIp cria uma nova regra
para o grupo de segurança. Aqui, o código manipula duas exceções comuns:
O Zend Framework emite uma exceção se você autorizar um intervalo de endereços IP
que já está autorizado, e uma segunda exceção ocorre quando o intervalo de endereços IP
estiver malformado. Para qualquer outra exceção, o código apenas realiza o dump
da mensagem de erro para a tela.
Observação: Um erro corrigido recentemente no Zend Framework retorna uma array de listagens quando mais de um intervalo de endereços estiver autorizado para uma determinada porta. Se sua versão do Zend Framework não tiver essa correção, você verá apenas um endereço para cada porta. Todas as autorizações são parte do grupo de segurança armazenado na nuvem Amazon; elas apenas não são mostradas nos resultados do Zend. O código de amostra possui uma lógica para manipular isso de forma elegante.
Finalmente, clicar no botão Revoke próximo à regra solicita a confirmação do usuário.
Figura 20. A exclusão de uma regra de segurança deve ser confirmada
A exclusão de uma regra de segurança é realizada por meio do método
revokeIp() .
Este artigo apresentou um conjunto de páginas para trabalhar com imagens de máquinas virtuais, instâncias em execução dessas imagens e os pares de chaves e grupos de segurança que permitem gerenciá-los. Mais uma vez, o Zend Framework torna mais fácil a interação com a nuvem. A próxima parte desta série mostrará como usar o Zend Framework para trabalhar com recursos mais avançados do EC2, com endereços IP elásticos, armazenamento em bloco elástico e CloudWatch.
| Descrição | Nome | Tamanho | Método de download |
|---|---|---|---|
| Sample code | os-php-cloud2-source.zip | 13KB | HTTP |
Informações sobre métodos de download
Aprender
- Você pode se inscrever para uma conta do Amazon Web Services na
página inicial do Amazon EC2.
-
O artigo
"Cloud
computing with Amazon Web Services, Part 3: Servers on demand with EC2" é uma excelente visão geral do EC2.
-
Descubra por que a computação em nuvem é importante,
como iniciar e onde aprender mais sobre ela no
espaço de Computação em nuvem .
-
O Wikipedia possui uma
boa discussão sobre o endereçamento CIDR.
-
PHP.net é o recurso central para o desenvolvedores PHP.
-
Consulte a "Lista de leitura PHP recomendada."
-
Navegue por todo o conteúdo PHP no developerWorks.
-
Acompanhe o developerWorks no Twitter.
-
Amplie suas habilidades em PHP consultando os recursos de projetos PHP.
-
Para ouvir entrevistas e discussões interessantes para desenvolvedores de software, confira os podcasts do developerWorks.
-
Usando um banco de dados com PHP? Confira o Zend Core para
IBM, um ambiente de desenvolvimento e produção PHP consistente, independente e fácil de instalar que suporta o IBM DB2 V9.
-
Fique atualizado com os Eventos Técnicos e Webcasts.
-
Confira as próximas conferências, exposições, webcasts e outros Eventos em todo o mundo que são interessantes para os desenvolvedores de software livre da IBM.
-
Visite a área de Software livre do developerWorks para obter informações instrutivas extensivas, ferramentas e atualizações de projetos para ajudá-lo a desenvolver com tecnologias de software livre e usá-las com produtos IBM, como também nossos artigos e tutoriais mais populares.
-
Assista e aprenda sobre a IBM e as tecnologias de software livre e funções de produtos com as demonstrações On Demand gratuitas do developerWorks.
Obter produtos e tecnologias
-
Faça o download do
Zend Server Community Edition
para executar os exemplos deste artigo.
-
Inove em seu próximo projeto de desenvolvimento de software livre com o software experimental IBM, disponível para download ou em DVD.
- Faça o download de
Versões de avaliação de produtos IBM
ou explore as avaliações on-line no IBM SOA Sandbox e obtenha ferramentas de desenvolvimento de aplicativos e produtos middleware DB2®, Lotus®, Rational®, Tivoli® e WebSphere®.
Discutir
-
Visite os blogs do developerWorks e participe da comunidade do developerWorks.
-
Participe do Fórum PHP: Developing PHP applications with IBM Information Management products (DB2, IDS).

Doug Tidwell é um engenheiro de software sênior no grupo Emerging Technology da IBM. Ele foi um palestrante na primeira conferência sobre XML em 1997 e trabalhou com linguagem de marcações, serviços da Web e tecnologia SOA por vários anos. Seu trabalho como um evangelista de tecnologia é explicar os padrões e tecnologias por trás da computação em nuvem e ajudar clientes a integrá-los com suas arquiteturas e estratégias gerais de negócios. Ele é autor de vários artigos aqui no developerWorks e é o autor do livro sobre XSLT da O'Reilly (ISBN 0-596-52721-7), um presente inteligente para todas as ocasiões. Ele reside em Chapel Hill, N.C., com sua esposa, filha e cão.