Dear guys

I encountered a problem that a ssh public key of ssh_keypairs for a
newly created instance is overridden by another ssh key in template
meta data. I think this leads to security vulnerability because a
template owner can login to other user's instance created from the
template. So, could you fix this issue?

This behavior is caused by meta data import at commitUserVm method. A
ssh key value specified by an instance owner is set to a UserVmVO
object at line 2986-2988 of
server/src/com/cloud/vm/UserVmManagerImpl.java in 4.3 branch [1], but
this value is overridden at line 3035-3038 by template meta data.

Please note a database contains meta data entries related to a
template which you created from an instance in cloud.template_view
like [2]. 2nd row has detail_name and detail_value about ssh key and
CloudStack override the user specified ssh key value by the owner's
detail value in this situation. It results in delivery of the template
owner's ssh key for the instance created from the template to virtual
router inspite of specification of instance owner's ssh key.

You can reproduce this phenomenon like below.

    1. Deploy an instance with a ssh key A by specifying 'keypair'
       value.
    2. Create a template from this instance.
    3. Deploy an instance with another ssh key B by specifying
       'keypair' value.


[1] server/src/com/cloud/vm/UserVmManagerImpl.java

   2971     private UserVmVO commitUserVm(final DataCenter zone, final
VirtualMachineTemplate template, final String hostName, final String
displayName, final Account owner,
   2972         final Long diskOfferingId, final Long diskSize, final
String userData, final HypervisorType hypervisor, final Account
caller, final Boolean isDisplayVmEnabled,
   2973         final String keyboard, final long accountId, final
ServiceOfferingVO offering, final boolean isIso, final String
sshPublicKey,
   2974         final LinkedHashMap<String, NicProfile> networkNicMap,
final long id, final String instanceName, final String uuidName, final
HypervisorType hypervisorType,
   2975         final Map<String, String> customParameters) throws
InsufficientCapacityException {
   2976         return Transaction.execute(new
TransactionCallbackWithException<UserVmVO,
InsufficientCapacityException>() {
   2977             @Override
   2978             public UserVmVO doInTransaction(TransactionStatus
status) throws InsufficientCapacityException {
   2979                 UserVmVO vm = new UserVmVO(id, instanceName,
displayName,
   2980                         template.getId(), hypervisorType,
template.getGuestOSId(),
   2981                         offering.getOfferHA(),
offering.getLimitCpuUse(),
   2982                         owner.getDomainId(), owner.getId(),
offering.getId(), userData,
   2983                         hostName, diskOfferingId);
   2984                 vm.setUuid(uuidName);
   2985
vm.setDynamicallyScalable(template.isDynamicallyScalable());
   2986                 if (sshPublicKey != null) {
   2987                     vm.setDetail("SSH.PublicKey", sshPublicKey);
   2988                 }
   2989
   2990                 if (keyboard != null && !keyboard.isEmpty())
   2991                     vm.setDetail(VmDetailConstants.KEYBOARD, keyboard);
   2992
   2993                 if (isIso) {
   2994                     vm.setIsoId(template.getId());
   2995                 }
   2996
   2997                 if(isDisplayVmEnabled != null){
   2998                     if(!_accountMgr.isRootAdmin(caller.getType())){
   2999                         throw new PermissionDeniedException(
"Cannot update parameter displayvm, only admin permitted ");
   3000                     }
   3001                     vm.setDisplayVm(isDisplayVmEnabled);
   3002                 }else {
   3003                     vm.setDisplayVm(true);
   3004                 }
   3005
   3006                 // If hypervisor is vSphere, check for clone
type setting.
   3007                 if (hypervisorType.equals(HypervisorType.VMware)) {
   3008                     // retrieve clone flag.
   3009                     UserVmCloneType cloneType = UserVmCloneType.linked;
   3010                     String value =
_configDao.getValue(Config.VmwareCreateFullClone.key());
   3011                     if (value != null) {
   3012                         if (Boolean.parseBoolean(value) == true)
   3013                             cloneType = UserVmCloneType.full;
   3014                     }
   3015                     UserVmCloneSettingVO vmCloneSettingVO =
new UserVmCloneSettingVO(id, cloneType.toString());
   3016                     _vmCloneSettingDao.persist(vmCloneSettingVO);
   3017                 }
   3018
   3019                 long guestOSId = template.getGuestOSId();
   3020                 GuestOSVO guestOS = _guestOSDao.findById(guestOSId);
   3021                 long guestOSCategoryId = guestOS.getCategoryId();
   3022                 GuestOSCategoryVO guestOSCategory =
_guestOSCategoryDao.findById(guestOSCategoryId);
   3023
   3024
   3025                 // If hypervisor is vSphere and OS is OS X,
set special settings.
   3026                 if (hypervisorType.equals(HypervisorType.VMware)) {
   3027                     if
(guestOS.getDisplayName().toLowerCase().contains("apple mac os")){
   3028                         vm.setDetail("smc.present", "TRUE");
   3029
vm.setDetail(VmDetailConstants.ROOK_DISK_CONTROLLER, "scsi");
   3030                         vm.setDetail("firmware", "efi");
   3031                         s_logger.info("guestOS is OSX :
overwrite root disk controller to scsi, use smc and efi");
   3032                     }
   3033                 }
   3034
   3035                 Map<String, String> details = template.getDetails();
   3036                 if ( details != null && !details.isEmpty() ) {
   3037                     vm.details.putAll(details);
   3038                 }
   3039
   3040                 _vmDao.persist(vm);
   3041                 if (customParameters != null &&
customParameters.size() > 0) {
   3042                     for (String key : customParameters.keySet()) {
   3043                         vm.setDetail(key, customParameters.get(key));
   3044                     }
   3045                 }
   3046                 _vmDao.saveDetails(vm);

[2] database example

mysql> select * from cloud.template_view where id=207 \G;
*************************** 1. row ***************************
                  id: 207
                uuid: c96f0d9a-0a56-4d30-af73-fe8b31ae37c3
         unique_name: 2219faa5a-4e7b-3425-b6e6-135ab210422b
                name: cluster_frontend-20140520.2
              public: 1
            featured: 0
                type: USER
                 hvm: 1
                bits: 64
                 url: NULL
              format: QCOW2
             created: 2014-05-20 09:33:47
            checksum: NULL
        display_text: Cluster Frontend VM CentOS 6.5 ver.20140520.2
     enable_password: 1
dynamically_scalable: 0
      template_state: Active
         guest_os_id: 182
       guest_os_uuid: 9d3c42d8-caab-11e3-9125-001e679910a0
       guest_os_name: CentOS 6.4 (64-bit)
            bootable: 1
         prepopulate: 0
         cross_zones: 0
     hypervisor_type: KVM
         extractable: 0
        template_tag: NULL
            sort_key: 0
             removed: NULL
       enable_sshkey: 0
  source_template_id: 205
source_template_uuid: c131680c-3e0e-4d7c-b554-02dabc10ade1
          account_id: 3
        account_uuid: f9e4e1ca-69fd-4ae3-b70c-15bbcc13406e
        account_name: sgcadm
        account_type: 0
           domain_id: 2
         domain_uuid: 84dd635d-fb99-4895-b199-7d777aa144d5
         domain_name: default
         domain_path: /default/
          project_id: NULL
        project_uuid: NULL
        project_name: NULL
      data_center_id: NULL
    data_center_uuid: NULL
    data_center_name: NULL
       lp_account_id: NULL
            store_id: 3
         store_scope: REGION
               state: Ready
      download_state: DOWNLOADED
        download_pct: 100
           error_str: NULL
                size: 18465816576
           destroyed: 0
    created_on_store: 2014-05-20 09:33:47
         detail_name: Message.ReservedCapacityFreed.Flag
        detail_value: false
              tag_id: NULL
            tag_uuid: NULL
             tag_key: NULL
           tag_value: NULL
       tag_domain_id: NULL
      tag_account_id: NULL
     tag_resource_id: NULL
   tag_resource_uuid: NULL
   tag_resource_type: NULL
        tag_customer: NULL
      temp_zone_pair: 207_0
*************************** 2. row ***************************
                  id: 207
                uuid: c96f0d9a-0a56-4d30-af73-fe8b31ae37c3
         unique_name: 2219faa5a-4e7b-3425-b6e6-135ab210422b
                name: cluster_frontend-20140520.2
              public: 1
            featured: 0
                type: USER
                 hvm: 1
                bits: 64
                 url: NULL
              format: QCOW2
             created: 2014-05-20 09:33:47
            checksum: NULL
        display_text: Cluster Frontend VM CentOS 6.5 ver.20140520.2
     enable_password: 1
dynamically_scalable: 0
      template_state: Active
         guest_os_id: 182
       guest_os_uuid: 9d3c42d8-caab-11e3-9125-001e679910a0
       guest_os_name: CentOS 6.4 (64-bit)
            bootable: 1
         prepopulate: 0
         cross_zones: 0
     hypervisor_type: KVM
         extractable: 0
        template_tag: NULL
            sort_key: 0
             removed: NULL
       enable_sshkey: 0
  source_template_id: 205
source_template_uuid: c131680c-3e0e-4d7c-b554-02dabc10ade1
          account_id: 3
        account_uuid: f9e4e1ca-69fd-4ae3-b70c-15bbcc13406e
        account_name: sgcadm
        account_type: 0
           domain_id: 2
         domain_uuid: 84dd635d-fb99-4895-b199-7d777aa144d5
         domain_name: default
         domain_path: /default/
          project_id: NULL
        project_uuid: NULL
        project_name: NULL
      data_center_id: NULL
    data_center_uuid: NULL
    data_center_name: NULL
       lp_account_id: NULL
            store_id: 3
         store_scope: REGION
               state: Ready
      download_state: DOWNLOADED
        download_pct: 100
           error_str: NULL
                size: 18465816576
           destroyed: 0
    created_on_store: 2014-05-20 09:33:47
         detail_name: SSH.PublicKey
        detail_value: ssh-rsa ...(snip)
              tag_id: NULL
            tag_uuid: NULL
             tag_key: NULL
           tag_value: NULL
       tag_domain_id: NULL
      tag_account_id: NULL
     tag_resource_id: NULL
   tag_resource_uuid: NULL
   tag_resource_type: NULL
        tag_customer: NULL
      temp_zone_pair: 207_0
*************************** 3. row ***************************
                  id: 207
                uuid: c96f0d9a-0a56-4d30-af73-fe8b31ae37c3
         unique_name: 2219faa5a-4e7b-3425-b6e6-135ab210422b
                name: cluster_frontend-20140520.2
              public: 1
            featured: 0
                type: USER
                 hvm: 1
                bits: 64
                 url: NULL
              format: QCOW2
             created: 2014-05-20 09:33:47
            checksum: NULL
        display_text: Cluster Frontend VM CentOS 6.5 ver.20140520.2
     enable_password: 1
dynamically_scalable: 0
      template_state: Active
         guest_os_id: 182
       guest_os_uuid: 9d3c42d8-caab-11e3-9125-001e679910a0
       guest_os_name: CentOS 6.4 (64-bit)
            bootable: 1
         prepopulate: 0
         cross_zones: 0
     hypervisor_type: KVM
         extractable: 0
        template_tag: NULL
            sort_key: 0
             removed: NULL
       enable_sshkey: 0
  source_template_id: 205
source_template_uuid: c131680c-3e0e-4d7c-b554-02dabc10ade1
          account_id: 3
        account_uuid: f9e4e1ca-69fd-4ae3-b70c-15bbcc13406e
        account_name: sgcadm
        account_type: 0
           domain_id: 2
         domain_uuid: 84dd635d-fb99-4895-b199-7d777aa144d5
         domain_name: default
         domain_path: /default/
          project_id: NULL
        project_uuid: NULL
        project_name: NULL
      data_center_id: NULL
    data_center_uuid: NULL
    data_center_name: NULL
       lp_account_id: NULL
            store_id: 3
         store_scope: REGION
               state: Ready
      download_state: DOWNLOADED
        download_pct: 100
           error_str: NULL
                size: 18465816576
           destroyed: 0
    created_on_store: 2014-05-20 09:33:47
         detail_name: Encrypted.Password
        detail_value: ...(snip)
              tag_id: NULL
            tag_uuid: NULL
             tag_key: NULL
           tag_value: NULL
       tag_domain_id: NULL
      tag_account_id: NULL
     tag_resource_id: NULL
   tag_resource_uuid: NULL
   tag_resource_type: NULL
        tag_customer: NULL
      temp_zone_pair: 207_0
3 rows in set (0.00 sec)

ERROR:
No query specified

mysql>


Best Regards

-- 
Hiroki Ohashi

Reply via email to